Strange behavior PHP unpack - php

Help to understand how works PHP's unpack.
I know that in ruby I can use unpack somehow:
"abcdefgh-abcdefgh-abcdefgh-abcdefgh".unpack("NnnnnN")
=> [1633837924, 25958, 26472, 11617, 25187, 1684366951]
Given the documentation in PHP too. But actually it does not really work.
I need array of 6 elements. Lets try to get it...
$bytes = openssl_random_pseudo_bytes(16);
var_dump(unpack("NnnnnN", $bytes));
array(1) {
["nnnnN"]=>
int(2679895791)
}
var_dump(unpack("N/n/n/n/n/N", $bytes));
array(1) {
[1]=>
int(600384068)
}
var_dump(unpack("N1/n1/n1/n1/n1/N1", $bytes));
array(1) {
[1]=>
int(600384068)
}
var_dump(unpack("N1n1n1n1n1N", $bytes));
array(1) { ["n1n1n1n1N"]=> int(2679895791) }
I found workaround:
var_dump(array_values(unpack("N1a/n1b/n1c/n1d/n1e/N1f", $bytes)));
array(6) {
[0]=>
int(2679895791)
[1]=>
int(39295)
[2]=>
int(42804)
[3]=>
int(32471)
[4]=>
int(39559)
[5]=>
int(600384068)
}
But I think there is a bit of black magic. Prompt please how correctly to use the unpack function without aliases (like N1a) and array_values?

No. Each format is evaluated by itself and overwrites the previous values:
var_dump(unpack("N", $bytes));
array(1) {
[1]=>
int(824184250)
}
var_dump(unpack("N/n", $bytes));
array(1) {
[1]=>
int(32979)
}
var_dump(unpack("N/n2", $bytes));
array(2) {
[1]=>
int(32979)
[2]=>
int(48930)
}
It's actually on the documentation you linked:
Caution
Be aware that if you do not name an element, an empty string is used. If you do not name more than one element, this means that some data is overwritten as the keys are the same [...]

Related

Extract arrays with string to a new array

I know that there are some posts at SO with a similar issue, but none of those could really help me solving mine. I do have the following $test array:
array(1) {
[0]=>
array(4) {
[0]=>
array(2) {
["id"]=>
string(8) "40265656"
["text"]=>
string(29) "10' - 1st Corner - Terengganu"
}
[1]=>
array(2) {
["id"]=>
string(8) "40265715"
["text"]=>
string(25) "18' - 2nd Corner - Pahang"
}
[2]=>
array(2) {
["id"]=>
string(8) "40265770"
["text"]=>
string(29) "23' - 3rd Corner - Terengganu"
}
[3]=>
array(3) {
["id"]=>
string(8) "40265830"
["text"]=>
string(29) "26' - 4th Corner - Pahang"
}
}
}
and would like to extract only those arrays containing Pahang in the ["text"] key. First I have tried
$key = array_search('Pahang', $test);
and that gives me bool(false). What am I doing wrong here?
I think this way will be right:
$result = [];
foreach ($array[0] as $arr) {
if (strpos($arr['text'], "Pahang") !== false) {
$result[] = $arr;
}
}
The function array_search(...) searches for a value inside an array, but your array is not flat, it's multidimensional, this means you have one or more arrays inside another array.
In your case, you can use array_filter(...) that allows you to filter your array elements in a callable function.
So, initially you have to define a function that filters the elements:
function getPahang($element) {
return $element['text'] === 'Pahang'
}
This function returns true when the element text value is equal to 'Pahang', instead it returns false.
Now, you have to call array_filter, by passing your array and the callable function:
$new_array = array_filter($test[0], 'getPahang');
You can try a similar script here: http://sandbox.onlinephpfunctions.com/code/c076222dd6d1c6f2675d0241742e6c11da6eff53

Coordinates from text to array [preg_match]

Maybe someone can help me get coordinates from text to array?
I'm trying use preg_match but no success.
I can remove geometry":{"paths":[[[**" and **]]}}]})
then use some times 'explode' and get coo, but I don't like this idea
Coordinates:
"geometry":{"paths":
[[[485749.91999999998,6108180.6500000004],
[485722.35999999999,6108206],
[485691.14000000001,6108234.3099999996],
[485400.84999999998,6108513.1500000004],
[485368.60999999999,6108545.46],
[485301.53999999998,6108613.1900000004],
[484054.82000000001,6109868.9100000001],
[484051.17566666665,6109872.6840000004]]]}}]});
To figure out my approach in the comment above. Convert the string to valid JSON. Afterwards you can decode the string using json_decode():
$jsonArr = json_decode('{' . substr($string, 0, -4), true);
$coordinates= $jsonArr['geometry']['paths'][0]);
var_dump($coordinates):
So you end up with an array of coordinate pairs:
array(8) {
[0]=>
array(2) {
[0]=>
float(485749.92)
[1]=>
float(6108180.65)
}
[1]=>
array(2) {
[0]=>
float(485722.36)
[1]=>
int(6108206)
}
[2]=>
array(2) {
[0]=>
float(485691.14)
[1]=>
float(6108234.31)
}
[3]=>
array(2) {
[0]=>
float(485400.85)
[1]=>
float(6108513.15)
}
[4]=>
array(2) {
[0]=>
float(485368.61)
[1]=>
float(6108545.46)
}
[5]=>
array(2) {
[0]=>
float(485301.54)
[1]=>
float(6108613.19)
}
[6]=>
array(2) {
[0]=>
float(484054.82)
[1]=>
float(6109868.91)
}
[7]=>
array(2) {
[0]=>
float(484051.175667)
[1]=>
float(6109872.684)
}
}
This is invalid Javascript object notation. Running it through JSONLint shows that it has an invalid array length. You might want to provide more context for your question.
Assuming you have something similar to the above but with valid JSON, you can use the json_decode method to convert a valid JSON string into PHP arrays and objects.

Comparing arrays in PHP - which order - string conversion errors

I var_dumped two arrays, the top on is the array coming in, $new_array, while the other one is a preexisting array $current_array:
// New Array
array(3) {
["Contributor"]=>
array(2) {
[0]=>
string(13) "edit_carousel"
[1]=>
string(13) "read_carousel"
}
["Editor"]=>
array(1) {
[0]=>
string(16) "delete_mini_feed"
}
["Author"]=>
array(3) {
[0]=>
string(11) "edit_blocks"
[1]=>
string(12) "edit_blockss"
[2]=>
string(12) "edit_blockss"
}
}
// Preexisting
array(3) {
["Contributor"]=>
array(2) {
[0]=>
string(13) "edit_carousel"
[1]=>
string(13) "read_carousel"
}
["Editor"]=>
array(4) {
[0]=>
string(16) "delete_mini_feed"
[1]=>
string(15) "edit_mini_feeds"
[2]=>
string(23) "edit_private_mini_feeds"
[3]=>
string(15) "edit_mini_feeds"
}
["Author"]=>
array(3) {
[0]=>
string(11) "edit_blocks"
[1]=>
string(12) "edit_blockss"
[2]=>
string(12) "edit_blockss"
}
}
I am trying to do something like: var_dump(array_intersect_assoc($current_array, $new_array)); to see whats different in the current array as opposed to the new array and generate an array of "differences" keeping the structure intact.
The issue is:
Is the order of arrays to be compared right? compare old to new and get an array of whats different in old. or should it be compare new to old?
Doing this, results in: Array to string conversion notice, but also prints out an array which is below.
I cant tell if these are: "these are whats not in old, but in new" or "the are whats not in new but in old" .... (It should say: these are not whats in old but in new).
array(3) {
["Contributor"]=>
array(2) {
[0]=>
string(13) "edit_carousel"
[1]=>
string(13) "read_carousel"
}
["Editor"]=>
array(4) {
[0]=>
string(16) "delete_mini_feed"
[1]=>
string(15) "edit_mini_feeds"
[2]=>
string(23) "edit_private_mini_feeds"
[3]=>
string(15) "edit_mini_feeds"
}
["Author"]=>
array(3) {
[0]=>
string(11) "edit_blocks"
[1]=>
string(12) "edit_blockss"
[2]=>
string(12) "edit_blockss"
}
}
The php function array_intersect_assoc() should return everything in the first array (aka $current_array) that exists in the second array (aka $new_array).
The issue that you are running into is that array_intersect_assoc() doesn't preform the key comparison recursively. It's only comparing the first level of keys (Contributor, Editor and Author).
Here's more information about the recursive issue. PHP Question: how to array_intersect_assoc() recursively
Your problem is that you are trying to perform array_intersect on a multidimensional array, but the function does string comparison of elements, resulting in array to string conversion error.
As you have the same keys in both arrays, the simplest solution is just to foreach through and to compare subsequent arrays(and you rather need array_diff if you want difference between the elements)
foreach($array_1 as $index => $sub_array) {
$sub_array_2 = $array_2[$index];
$diff = array_diff($sub_array, $sub_array_2);
// do something with diff
}
UPDATE
If You want to get everything that's not in array_1 but in array_2:
$result = [];
# lets find if there's any new elements
$keys_1 = array_keys($array_1);
$keys_2 = array_keys($array_2);
$diff = array_diff($keys_1, $keys_2);
if(!empty($diff)) {
foreach($diff as $key) {
if(isset($array_2[$key])) {
# it's in array_2
$result[$key] = $array_2[$key];
}
}
}
# now get difference between shared elements
$intersection = array_intersect($keys_1, $keys_2);
foreach($intersection as $key) {
$element_1 = $array_1[$key];
$element_2 = $array_2[$key];
$diff = array_diff($element_1, $element_2);
if(sizeof($diff)) {
if(!isset($result[$key]) ||!is_array($result[$key]) ) {
$result[$key] = array($diff);
} else {
$result[$key][] = $diff;
}
}
}

Is it possible to change the types of array values in PHP?

I'm retrieving data from a MySQL table. This data comes as string values and I would prefer to work with floating-point numbers. Here is what I'm doing:
$array_duracao = $con->prepare("SELECT SUM(dt)/0.01666667 AS mysum FROM afunda_eleva");
$array_duracao->execute();
$result3 = $array_duracao->fetch(PDO::FETCH_NUM);
$duracao_afunda_eleva[] = $result3;
for($i=0;$i<sizeof($duracao_afunda_eleva);$i++)
{
$duracao_afunda_eleva1[]=settype($duracao_afunda_eleva[$i],"float");
}
When I call var_dump($duracao_afunda_eleva1), it displays the following:
array(3) {
[0]=> float(1)
[1]=> float(1)
[2]=> float(1)
}
And when I call var_dump($duracao_afunda_eleva), it displays this:
array(3) {
[0]=> array(1) {
[0]=> string(9) "3.6599993"
}
[1]=> array(1) {
[0]=> string(9) "7.0199986"
}
[2]=> array(1) {
[0]=> string(9) "1.3799997"
}
}
How can I change array values from strings to floating-point numbers?
As I see from var_dump($duracao_afunda_eleva) - $duracao_afunda_eleva is a multidimensional array. So if you want to typecast values you should do it with array values and not with array itself, your code should be (thanks to #Barmar):
for($i=0; $i<sizeof($duracao_afunda_eleva); $i++) {
$duracao_afunda_eleva1[] = floatval($duracao_afunda_eleva[$i][0]);
}
$float = (float) "1.234";
Demo: http://codepad.viper-7.com/I6wsAl
Change
$duracao_afunda_eleva1[]=settype($duracao_afunda_eleva[$i],"float");
to
$duracao_afunda_eleva1[]=floatval($duracao_afunda_eleva[$i]);

php array cut dimensions (return single 'row')

Is it possible to cut multiple dimensions in a php array?
example:
I want the 4th dimension of each first-level element
array(1) {
[0]=> array(5)
{
[0]=> string(_) "/opt/path [10823] (/home/path/file.xml)"
[1]=> string(_) "/opt/path"
[2]=> string(_) "10823"
[3]=> string(_) "(/home/path/file.xml)"
[4]=> string(_) "/home/path/file.xml"
}
}
=>
array(1){ ( [0]=> string(_) "/home/path/file.xml") }
is there an internal php function or a way to achieve this without a loop?
Use array_map :
function selectMyLine($line) {
return $line[4];
}
$result = array_map("selectMyLine", $data);
print_r($result);
You could alse do the same with array_walk, which directly edit your array instead of creating a new one.

Categories