I have an array that i need to pack with python to 16bit depth with
I have been doing this with php without any issues.
Array is just just large set of numbers like this - [1, 2, 3, 4, 5, 700, 540...]
With php I do this process in one line:
$encoded_string = pack("s*", ...$array); // Done
I can not for the love of god figure out how same can be done in python
I have read the documentation, I looked at examples and I can not get this done
Best I have is below and it does not work in any variation i have tried.
encoded_string = struct.pack('h', *array)
You have to call struct.pack on each member of your array:
import struct
nums = [1, 2, 3, 4, 5, 700, 540]
as_bytes = [struct.pack('h', i) for i in nums]
# Produces
[b'\x01\x00', b'\x02\x00', b'\x03\x00', b'\x04\x00', b'\x05\x00', b'\xbc\x02', b'\x1c\x02', b'\x08\x00']
and then that you can join into a single byte string if you want:
>>> b''.join(as_bytes)
b'\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\xbc\x02\x1c\x02'
Note: you can also use the endianness modifiers to specify the alignment for the output bytes.
Edit: #Proper reminded me that struct.pack's formatting also supports specifying the number of target packed types, so this can be done more easily by including the data length in an f-string with the format specifier:
>>> struct.pack(f'{len(data)}h', *data)
b'\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\xbc\x02\x1c\x02'
Thank you for the reply b_c to be honest I hate python with a passion at this point, there was another problem that i had to fix, the array was created as str and not int after it was "exploded". So it had to be remapped to int.
Your code does work, thank you.
There is a way to do it with my initial code, however you have to define number of values you want to process. It is possible to simply count number of values in the array and add than in to make it automated
data_array = map(int,data) # converts all values in the array to int
encoded_string = struct.pack('240s',*data_array) # 240 is number of values in the array
Since moving from Python to PHP, I find that the array, 'dict' in PHP , implements both list and dict:
$numlist = array(1, 2, 3, 4, 5);
$cat_and_mouse = array("tom"=>12, "jerry"=> 2);
and the frustrating array funcitons:
some of them should apply on a list, while others on a dict.
array_chunk array_column array_combine array_count_values
array_diff_assoc array_diff_key array_diff_uassoc
array_diff_ukey array_diff array_fill_keys array_fill
array_filter array_flip array_intersect_assoc
array_intersect_key array_intersect_uassoc array_intersect_ukey
array_intersect array_key_exists array_keys array_map
array_merge_recursive array_merge array_multisort array_pad
array_pop array_product array_push array_rand array_reduce
array_replace_recursive array_replace array_reverse array_search
array_shift ...
List and HashMap are quite different in most language, WHY PHP mix them together?
Arrays in PHP are always associative, as by the very definition a PHP array is an ordered map, which associates values to keys.
In fact, if you disseminate your example, you'll find that your first array maps keys to sequential indexes:
$numlist = array(1, 2, 3, 4, 5);
var_dump($numlist);
Results in:
array (size=5)
0 => int 1
1 => int 2
2 => int 3
3 => int 4
4 => int 5
Whereas
$cat_and_mouse = array("tom" => 12, "jerry" => 2);
var_dump($cat_and_mouse);
Results in:
array (size=2)
'tom' => int 12
'jerry' => int 2
Omitting the key simply creates the key for you automatically, starting with 0.
Hope this helps! :)
Because PHP is the best programming language... \s
2 years passed.
2 years ago, I moved from python to PHP, and 10 months ago, I moved from PHP to Java.
Great thanks to Java, everything is so neat and elegant, now I use Spring Boot to host my application, use Spring Data and Hibernate to persist my data, and there is Java 8 stream parallel to use multicore CPU. and the great maven, eclipse...
I can't believe I waste 2 years in PHP. I hope I never met it.
So I have a very big JSON string that represents a multidimensional array with 255 entries, each entry, being an array with 255 other entries, liek this:
0 => array(0, 1, ..., 255),
1 => array(0, 1, ..., 255),
...
255 => array(0, 1, ..., 255),
(the only difference is that the values from the 2nd level are strings made out of 2-3 characters in my case)
Could I retrieve a certain value from this encoded string based on a key, but without actually decoding it to an array?
for example, I may want to get $arr[37][78];
To do this currently I'd have to:
$arr = json_decode($string);
$value = $arr[37][78];
Which I'd like to avoid because the decoded string takes a huge amount of memory as an array...
No, not based on a key. Since at the point that you receive it it's a string, your only option is regex or substr(), using indexes.
I had an interesting discussion with my good developer friends. I wanted to create a random sequence of given array values but with maximum fragmentation, without any detectable patterns. This so called maximum randomness would be practically always identical for any unique sequence.
Example input array:
array(1, 2, 3, 4, 5);
Example result of a standard rand() function:
array(2, 3, 1, 5, 4);
What I don't like in the output above are the sequence values like "2, 3" and "5, 4", It's not fragmented enough.
Expecting result would/could be:
array(3, 5, 1, 4, 2);
So my question; is there any known formula to calculate the maximum randomness or for better choice of words, maximum fragmentation?
So what are you talking about, not randomization, it is sorting. The result of randomization should not depend on order of the initial data.
By fragmentation in this case it is necessary to understand the differences between the array before sorting and after. But it must be evaluated differently depending on the task. For example, one can evaluate the difference between the positions of the elements or it's order.
Sorting example.
<?
// it must be uksort() function with sequence formula, but for me easier do like this
$array = array(1, 2, 3, 4, 5);
uk_sort($array);
function uk_sort(&$array) {
for($i=0;$i<count($array);$i++) {
if($i%2==0) {
$even[] = $array[$i];
} else {
$odd[] = $array[$i];
}
}
$even[] = array_shift($even);
rsort($odd);
$array = array_merge($even, $odd);
}
print_r($array);
?>
Array
(
[0] => 3
[1] => 5
[2] => 1
[3] => 4
[4] => 2
)
You could split the list into two (or more) collections, shuffle those THEN mix them in order?
array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
array(1, 2, 3, 4, 5);
array(6, 7, 8, 9, 10);
array(2, 3, 1, 5, 4);
array(8, 7, 10, 9, 6);
array(2, 8, 3, 7, 1, 10, 5, 9, 4, 6)
This would give you a fairly high fragmentation but not the maximum.
I suspect to get the maximum would require a LOT more work.
Assuming the fragmentation is defined as the sum of the absolute differences of successive values, the maximum fragmentation sequence is not unique -- the reverse sequence will always have the exact same fragmentation and there're many more options, e.g. all the following orderings will have a fragmentation of 11, which is maximal for this array: (3,1,5,2,4), (3,2,5,1,4), (2,5,1,4,3), (2,4,1,5,3), (4,1,5,2,3), (4,2,5,1,3), (3,5,1,4,2), (3,4,1,5,2). There're yet more symmetries if one incorporates the difference between the last and the first element, too.
If one seeks to identify a particular maximum fragmentation sequence, e.g. the one "without a noticeable pattern", the latter notion has to be formalized and a search performed, which, I suspect, would be costly from the computational point of view, unless the objective can be formalized so as to permit efficient decoding. I suspect that for all practical purposes a good heuristic would suffice, e.g. inserting elements into an array one by one (greedy fashion) so as to maximize the gain in fragmentation on each step.
If the elements of the array are not numbers but some entities with a defined distance for each pair, however, the problem does become equivalent to the traveling salesman problem, as user802500 pointed out.
I think this sounds like a traveling salesman type problem, with the "distance" being the difference between two chosen entries, except your goal would be to maximize the total distance rather than minimize it.
I don't actually know a ton about the topic, but here's what I think I know:
There are algorithms for the traveling salesman problem, but they can be quite slow in the limit (they're NP-hard). On the other hand, there are good approximations, and simple cases may be solvable, though it will still be a non-trivial algorithm.
Depending on how important it is to have maximum fragmentation, you could also try a naive method: given an element, choose the next element so that it's quite distant from the given element. Then choose a next element, and so on. The problem with this is that your early choices can back you into a corner. So this won't work if fragmentation is quite important to you.
[2,5,1,3,4] // the first three choices force us to not fragment the last two
I am after a function which will let me sort a bunch of filenames over 4 arrays.
However, the a file must always end up in the same array - even if the number of files change.
Eg if I have files
myfile.html
anotherfile.html
morefiles.html
test.html
and my arrays
array1, array2, array3, array4
If I run this function then
array1 might get myfile.html and anotherfile.html
If I run it again and add some more files (or less files, like not pass anotherfile.html) then I would still expect array1 to get myfile.html
So just need some way to hash the filename which I can then use to point to a certain array, so not a random or one that checks how many files are in each array needs to be consistent.
There are many different ways to solve a task like this, what is below is a very basic introduction to the topic. If it is useful, great otherwise I hope it at least gives an idea what where you might want to go (or not!).
This example simple takes a hash of the filename (in this case MD5 just because you're probably familiar with it). The sscanf just gets the first character of the hash and turns it into a number between 0 and 15 (since md5() returns a hexadecimal number). Since we only want to distribute between four arrays, the modulus operator (%) is used so that $num will always result in 0, 1, 2 or 3 which is then used as an array key (c.f. your $array1, $array2, etc.).
$files = array('a.html','b.html','c.html','d.html');
$arrays = 4;
$array = array_fill(0, $arrays, array());
// For each file name put it into the appropriate slot in $array
foreach ($files as $filename) {
sscanf(md5($filename), '%1x', $hex);
$key = $hex % $arrays;
$array[$key][] = $filename;
}
// See what happened
var_dump($array);
For this particular example, the resulting array (which you can push into your separate variables if you like) has the following structure:
$array = array(
0 => array()
1 => array('c.html')
2 => array('d.html')
3 => array('a.html', 'b.html')
);