Turn string into multidimensional array using regex - php

I would like to turn the following string into an array:
prijs=0,209&orderby=price&order=undefined&posts_per_page=undefined
INTO
array(
[prijs] => Array
(
[0] => 0
[1] => 209
)
[orderby] => Array
(
[0] => price
)
[order] => Array
(
[0] => undefined
)
[posts_per_page] => Array
(
[0] => undefined
)
)
Something like that. Is that possible?
Now I'm using some foreach loops, but that's not so fast and ideal like a RegEx.
It's a script which needs to load as fast as possible, so every bit of improvement in the code may help.
The amount of arrays can be variable. But it will always be 2 levels deep, like above. And just one main array.

You don't need REGEX for this. The string you have shown looks like a URL query string, in which case $_GET will already hold the values you need:-
var_dump($_GET);
Should give you:-
array (size=4)
'prijs' => string '0,209' (length=5)
'orderby' => string 'price' (length=5)
'order' => string 'undefined' (length=9)
'posts_per_page' => string 'undefined' (length=9)
Otherwise you can use parse_string().
$values = array();
parse_str('prijs=0,209&orderby=price&order=undefined&posts_per_page=undefined', $values);
var_dump($values);
Output:
array (size=4)
'prijs' => string '0,209' (length=5)
'orderby' => string 'price' (length=5)
'order' => string 'undefined' (length=9)
'posts_per_page' => string 'undefined' (length=9)

Looks like you're in need of array_walk as it should be faster than a foreach even if it does pretty much the same thing it does it at a lower level.
as vascowhite suggested you can use $_GET if you have it or parse_str() to get an initial array, after that:
array_walk($array, function(&$n) {
$n = explode(',', $n);
});
Live code: http://3v4l.org/YfuKs
Results in exactly what you want (always having arrays instead of CSV strings):
Array
(
[prijs] => Array
(
[0] => 0
[1] => 209
)
[orderby] => Array
(
[0] => price
)
[order] => Array
(
[0] => undefined
)
[posts_per_page] => Array
(
[0] => undefined
)
)
PS: instead of explode() you can use preg_split('/,/', $n) since you mentioned RegEx and see which one is faster for you

$str = 'prijs=0,209&orderby=price&order=undefined&posts_per_page=undefined';
$array = preg_split('/[&]/' , $str);
foreach ($array as $a)
{
$a = preg_split('/[=]/' , $a);
$a[1] = preg_split('/[,]/' , $a[1]);
}
var_dump($array);

Well, you can use something like this:
<?php
parse_str("prijs=0,209&orderby=price&order=undefined&posts_per_page=undefined",$myArray);
$myArray['prijs'] = explode(",", $myArray['prijs']);
$myArray['orderby'] = explode(",", $myArray['orderby']);
$myArray['order'] = explode(",", $myArray['order']);
$myArray['posts_per_page'] = explode(",", $myArray['posts_per_page']);
print_r($myArray);
?>

function urlSplitter($input)
{
$step1Array = explode('&', $input);
$result = array();
foreach($step1Array as $element)
{
$parts = explode("=", $element);
$result[$parts[0]] = explode(",", $parts[1]);
}
return $result;
}
$result = urlSplitter("prijs=0,209&orderby=price&order=undefined&posts_per_page=undefined");
var_dump($result);

Related

Merge two stdClass object array in php

I have the following two stdClass array from a loop. Now I need to merge them when when the key 'id' matches.
array (size=1)
0 =>
object(stdClass)[28]
public 'id' => string '78' (length=2)
public 'quantity' => string '5' (length=1)
array (size=1)
1 =>
object(stdClass)[31]
public 'product_id' => string '78' (length=2)
public 'quantity' => string '1' (length=1)
So the final array become
array (size=1)
1 =>
object(stdClass)[31]
public 'product_id' => string '78' (length=2)
public 'quantity' => string '6' (length=1)
Any help on how to do that ? I decode the original data using json_decode from [{"id":"78","quantity":"1"}] this format of data.
If you add an extra parameter to the json_decode, you can get the data as an associative array, which is much easier to work with. I've done a couple of versions ( the first is PHP 7 ), pick one which works with your system.
<?php
error_reporting ( E_ALL );
ini_set ( 'display_errors', 1 );
$arr1 = json_decode('[{"id":"78","quantity":"1"}, {"id":"79","quantity":"3"}]', true);
$arr2 = json_decode('[{"id":"78","quantity":"5"}]', true);
$arr3 = array_merge($arr1, $arr2);
// V7
$result = [];
foreach ( $arr3 as $element ) {
$result[$element['id']] = ($result[$element['id']]??0)
+ $element['quantity'];
}
print_r($result);
// Prior to V7
$result = array();
foreach ( $arr3 as $element ) {
if ( !isset($result[$element['id']]) ){
$result[$element['id']] = 0;
}
$result[$element['id']] += $element['quantity'];
}
print_r($result);
I've added another element to show how this adds up, but the output of this is...
Array
(
[78] => 6
[79] => 3
)
Array
(
[78] => 6
[79] => 3
)
Here is a solution that maintains the format in your original question.
It also uses array_reduce which is a concise way to process an array.
<?php
$input1 = '[{"id":"78","quantity":"7800"},
{"id":"79","quantity":"7900"},
{"id":"80","quantity":"8000"}]';
$input2 = '[{"id":"78","quantity":"6"},
{"id":"79","quantity":"8"},
{"id":"80","quantity":"6"},
{"id":"81","quantity":"7"}]';
$input1Arr = json_decode($input1);
$input2Arr = json_decode($input2);
$combinedArrays = array_merge($input1Arr, $input2Arr);
echo "combinedArrays = " . print_r($combinedArrays, true) . "\n";
$result = array_reduce($combinedArrays,
function($intermediateResult, $item){
if ( ! array_key_exists($item->id, $intermediateResult) ) {
// First time encountering an object with this id
$intermediateResult[$item->id] = $item;
}
else {
// We have an object with this id already so just add the quantity
$intermediateResult[$item->id]->quantity += $item->quantity;
}
return $intermediateResult;
}, []);
// Get the values from the result array
print_r(array_values($result));

PHP Create querystring from multidimensional array without using loop

I have a multidimensional array. Like this.
Array
(
[38] => Array
(
[quantity] => 1
[price] => 149
[product_code] => 4578425
)
[39] => Array
(
[quantity] => 2
[price] => 300
[product_code] => 4578426
)
)
I want to create query string from these values like
https://www.domain.com/checkout.php?PRODS=4578425,4578426&QTY=1,2&CART=1
Without using loops...
I don't think AFAIK, it is possible, since you have arrays in array, so using implode won't help. But, using loops, yea.
Use this code:
$prods = array();
$qty = array();
foreach ($array as $item)
{
$prods[] = $item["product_code"];
$qty[] = $item["quantity"];
}
echo 'https://www.domain.com/checkout.php?PRODS=', implode(',', $prods),'&QTY=', implode(',', $qty),'&CART=1';
you can use implode() method
$array = array('lastname', 'email', 'phone');
$comma_separated = implode(",", $array);
echo $comma_separated; // lastname,email,phone
Yes i think there is a way,
You can use serialize to put it in a string and then unserialize to get it back to an array like this:
<?php
$arr = Array
(
38 => Array
(
'quantity' => 1,
'price' => 149,
'product_code' => 4578425
),
39 => Array
(
'quantity' => 2,
'price' => 300,
'product_code' => 4578426
)
);
$newarr = 'https://www.domain.com/checkout.php?string=';
$newarr .= serialize($arr);
?>
then you have this result:
https://www.domain.com/checkout.php?string=a:2:{i:38;a:3:{s:8:"quantity";i:1;s:5:"price";i:149;s:12:"product_code";i:4578425;}i:39;a:3:{s:8:"quantity";i:2;s:5:"price";i:300;s:12:"product_code";i:4578426;}}a:2:{i:38;a:3:{s:8:"quantity";i:1;s:5:"price";i:149;s:12:"product_code";i:4578425;}i:39;a:3:{s:8:"quantity";i:2;s:5:"price";i:300;s:12:"product_code";i:4578426;}}
No loops but it is not pretty!!!
If you wish to use this inside url I have to warn you. The url get method is only intended for short information like id's or other key values. If your url gets over 2000 characters most web-servers would have problems with it. Not sure if that was your intention.

Creating Associative Array in PHP

I have a multidimensional array.
$shop = array(
array("appn1", "pub1" ,"pub2" , "pub3"),
array("appn2", "pub1"),
array("appn3", "pub1" ,"pub2")
);
The first item in each array is application number and the rest in each array are the publication numbers. I get the first item(application number) and the last item of each array(latest publication number) like this
$index = count(array_keys($shop));
for($i=0;$i<$index;$i++){
$appln_nr = $shop[$i][0];
echo $appln_nr;
$publn_nr_index = count(array_keys($shop[$i]))-1;
$publn_nr = $shop[$i][$publn_nr_index];
echo $publn_nr;
}
Now I have application number and publication number for each inner array.
I want to create an associative array from the application numbers and publication numbers.
where the key should be the application number and its value is the publication number.
Thanks
EDIT
What I am getting from $shop array
Array
(
[0] => Array
(
[0] => appn1
[1] => pub1
[2] => pub2
[3] => pub3
)
[1] => Array
(
[0] => appn2
[1] => pub1
)
[2] => Array
(
[0] => appn3
[1] => pub1
[2] => pub2
)
)
And this is what I need in my associative array
Array(
"appn1" => "pub3"
"appn2" => "pub1"
"appn3" => "pub2"
)
Finally i understood what you wanted, after your edit XD:
$shop = array(
array("appn1", "pub1" ,"pub2" , "pub3"),
array("appn2", "pub1"),
array("appn3", "pub1" ,"pub2")
);
$shopNew = array();
foreach($shop as $value){
$shopNew[$value[0]] = end($value);
}
// now if you want you can replace $shop and unset $shopNew
$shop = $shopNew;
unset($shopNew);
print_r($shop);
the output is this:
Array (
[appn1] => pub3
[appn2] => pub1
[appn3] => pub2
)
You can try
$shop = array(
array("appn1","pub1","pub2","pub3"),
array("appn2","pub1"),
array("appn3","pub1","pub2")
);
$final = array();
array_map(function ($var) use(&$final) {$final[reset($var)] = end($var);}, $shop);
var_dump($final);
Output
array
'appn1' => string 'pub3' (length=4)
'appn2' => string 'pub1' (length=4)
'appn3' => string 'pub2' (length=4)
You can easily convert your array into a new format by using the first element as key (see reset) and the last element (see end) as value:
foreach($shop as $fl) {
$v[reset($fl)] = end($fl);
}
Result is in $v then.
If you want to transform the array you need to delete each element as well:
foreach($shop as $v => $fl) {
$shop[reset($fl)] = end($fl);
unset($shop[$v]);
}
Result is in $shop then. Unset takes care of removing from the array.
Output in both cases is:
array(3) {
'appn1' =>
string(4) "pub3"
'appn2' =>
string(4) "pub1"
'appn3' =>
string(4) "pub2"
}
try this:
foreach($shop as $k => $v) {
$new_arr[$v[0]] = end($v);
}
It should give you this result,
$new_arr = array(
"appn1" => "pub3",
"appn2" => "pub1",
"appn3" => "pub2"-
);
You can also create like this,
$arrField = [];
$arrField['id'] = '0001';
$arrField["first_name"] ='Demo Test';
print_r($arrField);
print_r($arrField) display output like this.
Array ( [id] => 0001 [first_name] => Demo Test )

Count number of different strings?

I have an array that looks like
Array
(
[1] => Array
(
[0] => Date
[1] => Action
)
[2] => Array
(
[0] => 2011-01-22 11:23:19
[1] => SHARE_TWEET
)
[3] => Array
(
[0] => 2011-01-22 11:23:19
[1] => SHARE_FACEBOOK
)
and many other different values (about 10), what I want to do is I want to count the number of times a string is in the array. I was going to use array_count_values but it doesn't count multidimensional arrays.
Any other options?
This could be done by first flattening the array, and then using array_count_values() on it:
For flattening, here is the trick:
$array = call_user_func_array('array_merge', $arrays);
And then:
$counts = array_count_values($array);
Output:
array (
'Date' => 1,
'Action' => 1,
'2011-01-22 11:23:19' => 2,
'SHARE_TWEET' => 1,
'SHARE_FACEBOOK' => 1,
)
Full code:
$array = call_user_func_array('array_merge', $arrays);
var_export(array_count_values($array));
Any time you're dealing with arrays, especially with loops in PHP I can't string enough suggest you look at the array documentation, You'd be suprised how quickly you realise most of the loops in your code is unnecessary. PHP has a built in function to achieve what you're after called array_walk_recursive. And since you're using PHP5 you can use closures rather that create_function (which can be very troublesome, especially to debug, and can't be optimised by the PHP interpreter afik)
$strings = array();
array_walk_recursive($arr, function($value, $key) use (&$strings) {
$strings[$value] = isset($strings[$value]) ? $strings[$value]+1 : 1;
});
I know, unary statements aren't always clear, but this one is simple enough, but feel free to expand out the if statement.
The result of the above is:
print_r($strings);
Array
(
[Date] => 1,
[Action] => 1,
[2011-01-22 11:23:19] => 2,
[SHARE_TWEET] => 1,
[SHARE_FACEBOOK] => 1,
)
Pseudo Code
$inputArray = // your array as in the example above
foreach ($inputArray as $key => $value) {
$result[$value[1]] = $result[$value[1]] + 1;
}
var_dump($result);
Here is a way to do the job:
$arr = Array (
1 => Array (
0 => 'Date',
1 => 'Action'
),
2 => Array (
0 => '2011-01-22 11:23:19',
1 => 'SHARE_TWEET'
),
3 => Array (
0 => '2011-01-22 11:23:19',
1 => 'SHARE_FACEBOOK'
)
);
$result = array();
function count_array($arr) {
global $result;
foreach($arr as $k => $v) {
if (is_array($v)) {
count_array($v);
} else {
if (isset($result[$v])) {
$result[$v]++;
} else {
$result[$v] = 1;
}
}
}
}
count_array($arr);
print_r($result);
output:
Array
(
[Date] => 1
[Action] => 1
[2011-01-22 11:23:19] => 2
[SHARE_TWEET] => 1
[SHARE_FACEBOOK] => 1
)

Find all second level keys in multi-dimensional array in php

I want to generate a list of the second level of keys used. Each record does not contain all of the same keys. But I need to know what all of the keys are. array_keys() doesn't work, it only returns a list of numbers.
Essentially the output Im looking for is:
action, id, validate, Base, Ebase, Ftype, Qty, Type, Label, Unit
I have a large multi-dimensional array that follows the format:
Array
(
[0] => Array
(
[action] => A
[id] => 1
[validate] => yes
[Base] => Array
(
[id] => 2945
)
[EBase] => Array
(
[id] => 398
)
[Qty] => 1
[Type] => Array
(
[id] => 12027
)
[Label] => asfhjaflksdkfhalsdfasdfasdf
[Unit] => asdfas
)
[1] => Array
(
[action] => A
[id] => 2
[validate] => yes
[Base] => Array
(
[id] => 1986
)
[FType] => Array
(
[id] => 6
)
[Qty] => 1
[Type] => Array
(
[id] => 13835
)
[Label] => asdssdasasdf
[Unit] => asdger
)
)
Thanks for the help!
<?php
// Gets a list of all the 2nd-level keys in the array
function getL2Keys($array)
{
$result = array();
foreach($array as $sub) {
$result = array_merge($result, $sub);
}
return array_keys($result);
}
?>
edit: removed superfluous array_reverse() function
array_keys(call_user_func_array('array_merge', $a));
Merge all values and retrieve the resulting keys.
One liner:
$keys=array_unique(array_reduce(array_map('array_keys',$data),'array_merge',[]));
Or in a function:
function get_array_children_keys($data) {
return array_unique(
array_reduce(array_map('array_keys', $data), 'array_merge', [])
);
}
Now lets break this down with an example, here is some sample data:
[
['key1' => 0],
['key1' => 0, 'key2' => 0],
['key3' => 0]
]
Starting with the inner most function, we run array_map with the array_keys function:
array_map('array_keys', $data)
This gives us the keys of from all child arrays
[
['key1'],
['key1', 'key2'],
['key3']
]
Then we run the array_reduce on the data with the array_merge callback and an empty array as the initial value:
array_reduce(..., 'array_merge', []);
This converts our multiple arrays into 1 flat array:
[
'key1',
'key1',
'key2',
'key3'
]
Now we strip out our duplicates with array_unique:
array_unique(...)
And end up with all our keys:
[
'key1',
'key2',
'key3'
]
foreach($bigArray as $array){
foreach($array as $key=>$value){
echo $key;
}
}
That should do what you want.
What about something like this :
$your_keys = array_keys($your_array[0]);
Of course, this is considering all sub-arrays have the same keys ; in this case, you only need the keys of the first sub-array (no need to iterate over all first-level sub-arrays, I guess)
And, as a shortened / simplified example :
$your_array = array(
array(
'action' => 'A',
'id' => 1,
'base' => array('id' => 145),
),
array(
'action' => 'B',
'id' => 2,
'base' => array('id' => 145),
),
array(
'action' => 'C',
'id' => 3,
'base' => array('id' => 145),
)
);
$your_keys = array_keys($your_array[0]);
var_dump($your_keys);
Will get you :
array
0 => string 'action' (length=6)
1 => string 'id' (length=2)
2 => string 'base' (length=4)
You can the use implode to get the string you asked for :
echo implode(', ', $your_keys);
will get you :
action, id, base
ie, the list of the keys of the first sub-array.
function __getAll2Keys($array_val){
$result = array();
$firstKeys = array_keys($array_val);
for($i=0;$i<count($firstKeys);$i++){
$key = $firstKeys[$i];
$result = array_merge($result,array_keys($array_val[$key]));
}
return $result;
}
try this function. It will return as you want.
While #raise answers provides a shortcut, it fails with numeric keys. The following should resolve this:
$secondKeys=array_unique(call_user_func_array('array_merge', array_map('array_keys',$a)));
array_map('array_keys',$a) : Loop through while getting the keys
...'array_merge'... : Merge the keys array
array_unique(... : (optional) Get unique keys.
I hope it helps someone.
UPDATE:
Alternatively you can use
$secondKeys=array_unique(array_merge(...array_map('array_keys', $a)));
That provides same answer as above, and much faster.
My proposal, similar to this answer but faster and using spread operator (PHP 5.6+).
array_merge(...array_values($fields))
if you want move names to array values and reset keys to 0..n just use array_keys in last step.
array_keys(array_merge(...array_values($fields)))
Maybe you can use array_map function, which allows you to avoid array iteration and return an array with the keys you need as values.
will be like this
$newArray = array_map(function($value){return array_keys($value);},$yourArray);
var_dump($newArray);
array (size=2)
0 =>
array (size=9)
0 => string 'action' (length=6)
1 => string 'id' (length=2)
2 => string 'validate' (length=8)
3 => string 'Base' (length=4)
4 => string 'EBase' (length=5)
5 => string 'Qty' (length=3)
6 => string 'Type' (length=4)
7 => string 'Label' (length=5)
8 => string 'Unit' (length=4)
1 =>
array (size=9)
0 => string 'action' (length=6)
1 => string 'id' (length=2)
2 => string 'validate' (length=8)
3 => string 'Base' (length=4)
4 => string 'FType' (length=5)
5 => string 'Qty' (length=3)
6 => string 'Type' (length=4)
7 => string 'Label' (length=5)
8 => string 'Unit' (length=4)
With this function you can get all keys from a multidimensional array
function arrayKeys($array, &$keys = array()) {
foreach ($array as $key => $value) {
$keys[] = $key;
if (is_array($value)) {
$this->arrayKeys($value, $keys);
}
}
return $keys;
}
Only if all records have the same keys you could do:
$firstItem = reset($array);
$keys = array_keys($firstItem);
Obviously, this is not the correct answer to this specific question, where the records have different keys. But this might be the question you find when looking how to retrieve second level keys from an array where all keys are the same (I did). If all the record have the same keys, you can simply use the first item in the array with reset() and get the keys from the first item with array_keys().

Categories