Re-grouping array into multidimensional using several values - php

What I have:
array(
[
'id' => 12, 'group' => 'abc', 'name' => 'Lorem',
],
[
'id' => 12, 'group' => 'def', 'name' => 'Ipsum',
],
[
'id' => 34, 'group' => 'ghi', 'name' => 'Dolor',
],
[
'id' => 34, 'group' => 'jkl', 'name' => 'Sit',
],
[
'id' => 34, 'group' => 'mno', 'name' => 'Amet',
],
);
What I want:
array (size=2)
12 =>
array (size=2)
'abc' =>
array (size=3)
'id' => int 12
'group' => string 'abc' (length=3)
'name' => string 'Lorem' (length=5)
'def' =>
array (size=3)
'id' => int 12
'group' => string 'def' (length=3)
'name' => string 'Ipsum' (length=5)
34 =>
array (size=3)
'ghi' =>
array (size=3)
'id' => int 34
'group' => string 'ghi' (length=3)
'name' => string 'Dolor' (length=5)
'jkl' =>
array (size=3)
'id' => int 34
'group' => string 'jkl' (length=3)
'name' => string 'Sit' (length=3)
'mno' =>
array (size=3)
'id' => int 34
'group' => string 'mno' (length=3)
'name' => string 'Amet' (length=4)
What I tried:
The obvious:
$sorted = array();
foreach ($products as $product) {
$sorted[$product['id']][$product['group']] = $product;
}
$products = $sorted;
unset($sorted);
But then, in an effort to avoid foreach() loops, and with help of #atomrc's answer to How to group subarrays by a column value?, I came up with this:
$sorted = array_reduce($products, function ($accumulator, $element) {
$accumulator[$element['id']][] = $element;
return $accumulator;
}, []);
array_walk($sorted, function(&$item) {
$item = array_reduce($item, function ($accumulator, $element) {
$accumulator[$element['group']] = $element;
return $accumulator;
}, []);
});
So while the above looks cool and all, it's also much bigger and seemingly more complex than that foreach. This is probably because my experience with array_reduce() is limited. Is there a way to have the array grouped in one go? For example, in the first array_reduce() call.

Personally I don't see an issue with the foreach solution, but if you want to use array_reduce you can simply use the inner code from the foreach loop:
$grouped = array_reduce($products, function ($c, $v) {
$c[$v['id']][$v['group']] = $v;
return $c;
}, []);
print_r($grouped);
The output of this code is the same as your foreach loop.
Note that this (and your foreach loop) won't deal correctly with the situation where there is more than one array with the same id and group values. For example, if we extend $products:
$products[] = [
'id' => 34, 'group' => 'jkl', 'name' => 'Consectetur',
];
Then the first jkl group value gets overwritten by the second. To deal with this you need to make each group an array e.g.
$grouped = array_reduce($products, function ($c, $v) {
$c[$v['id']][$v['group']][] = $v;
return $c;
}, []);
print_r($grouped);
In this case the jkl group then looks like:
[jkl] => Array
(
[0] => Array
(
[id] => 34
[group] => jkl
[name] => Sit
)
[1] => Array
(
[id] => 34
[group] => jkl
[name] => Consectetur
)
)
Demo on 3v4l.org

Related

Add array to Value

After a $single_array = array_reduce ($new_array, 'array_merge_recursive', array ());
I get this result
array (size=9)
'key1' => string 'value1'
'key2' => string 'value2'
'key3' => string 'value3'
'key7' =>
array
0 => string 'value7'
1 => string 'value13'
'key8' =>
array
0 => string 'value8'
1 => string 'value14'
'key9' =>
array
0 => string 'value9'
1 => string 'value15'
'key19' => string 'value19'
'key20' => string 'value20'
'key21' => string 'value21'
but i would like that
array
'key1' =>
array
0 => string 'value1'
'key2' =>
array
0 => string 'value2'
'key3' =>
array
0 => string 'value3'
'key7' =>
array
0 => string 'value7'
1 => string 'value13'
'key8' =>
array
0 => string 'value8'
1 => string 'value14'
'key9' =>
array
0 => string 'value9'
1 => string 'value15'
'key19' =>
array
0 => string 'value19'
'key20' =>
array
0 => string 'value20'
'key21' =>
array
0 => string 'value21'
It's probably very simple, but I've been blocking for a few hours.
In short, I would like my array_merge_recursive not to add a key only to the same values, but to add an array[0] also to those which were not the same.
EDIT
The code at the start, the goal being to simplify it and knowing that the values generated as well as the order of the structure can be random.
<?php
$array = array(
'sensors' => array(
'0' => array(
'data' => array(
'0' => array(
'key1' => 'value1',
'key2' => 'value2',
'key3' => 'value3',
)
)
),
'1' => array(
'data' => array(
'0' => array(
'key7' => 'value7',
'key8' => 'value8',
'key9' => 'value9',
)
)
),
'2' => array(
'data' => array(
'0' => array(
'key7' => 'value13',
'key8' => 'value14',
'key9' => 'value15',
)
)
),
'3' => array(
'data' => array(
'0' => array(
'key19' => 'value19',
'key20' => 'value20',
'key21' => 'value21',
)
)
)
)
);
$new_array = array();
foreach ($array as $element1) {
foreach ($element1 as $j => $element2) {
foreach ($element2 as $element3) {
foreach ($element3 as $element4) {
$new_array[$j] = $element4;
$single_array = array_reduce($new_array, 'array_merge_recursive', array());
}
}
}
}
var_dump($single_array);
You can use array_walk_recursive on the original array:
$result = [];
array_walk_recursive($array, function ($value, $key) use (&$result) {
$result[$key][] = $value;
});
After running this on the example array you provided, $result will be:
[
'key1' => ['value1'],
'key2' => ['value2'],
'key3' => ['value3'],
'key7' => ['value7', 'value13'],
'key8' => ['value8', 'value14'],
'key9' => ['value9', 'value15'],
'key19' => ['value19'],
'key20' => ['value20'],
'key21' => ['value21']
];
Thank you, I found, I was just confusing in_array and is_array. My bad
$array2 = array();
foreach ($single_array as $key1 => $value1) {
if (is_array($value1)) {
foreach($value1 as $key2 => $value2) {
$array2[$key1][$key2] = $value2;
}
}
else {
$array2[$key1][] = $value1;
}
}
var_dump($array2);

best way to make this array multidimensionnal

i have array like :
$options = array (
'af' => 'Afrikaans',
'af_NA' => 'Afrikaans (Namibiƫ)',
'af_ZA' => 'Afrikaans (Suid-Afrika)',
);
i want to add key for the country and for the id like :
$options = array (
[0]=> array (
'id' => 'af'
'name' => 'Afrikaans',
),
[1]=> array (
'id' => 'af_NA'
'name' => 'Afrikaans (Namibie)',
),
)
Make an empty array and then push new arrays onto it after you map your new values correctly.
$new = array();
foreach ($options as $key => $value) {
array_push($new, array("id" => $key, "name" => $value));
}
$options = $new;
You could use a map with lambda:
$result = array_map(function ($id, $name) { return array('id' => $id,'name' => $name); }, array_keys($options), $options);
var_dump($result);
Output:
array (size=3)
0 =>
array (size=2)
'id' => string 'af' (length=2)
'name' => string 'Afrikaans' (length=9)
1 =>
array (size=2)
'id' => string 'af_NA' (length=5)
'name' => string 'Afrikaans (Namibiƫ)' (length=20)
2 =>
array (size=2)
'id' => string 'af_ZA' (length=5)
'name' => string 'Afrikaans (Suid-Afrika)' (length=23)

php array merge on key using multidimensional array [duplicate]

This question already has answers here:
Merge row data from multiple arrays
(6 answers)
Closed 4 months ago.
This is my array:
array
0 =>
array
'id' => int 220950
'order_reference' => string '600125479'
1 =>
array
'id' => int 220985
'order_reference' => string '498638'
and this my another array
array
0 =>
array
'entity_id' => 1
'order_status' => 'test'
1 =>
array
'entity_id' => 2
'order_status' => 'test2'
and my goal is to achieve this:
array
0 =>
array
'id' => int 220950
'order_reference' => string '600125479'
'entity_id' => 1
'order_status' => 'test'
1 =>
array
'id' => int 220985
'order_reference' => string '498638'
'entity_id' => 2
'order_status' => 'test2'
with array_merge I managed to get this(NOT my desired goal) and this all I found on stackoverflow and other forums:
array
0 =>
array
'id' => int 220950
'order_reference' => string '600125479'
1 =>
array
'id' => int 220985
'order_reference' => string '498638'
array
2 =>
array
'entity_id' => 1
'order_status' => 'test'
3 =>
array
'entity_id' => 2
'order_status' => 'test2'
Any ideas or suggestions are welcomed :) thank you
Using a foreach I can add the keys values, but I am looking for a more cleanest way :)
Here's the answer to your question using array_map and array_merge_recursive.
<?php
$array1 = array(
[
"id" => 220950,
"order_reference" => "600125479"
],
[
"id" => 220985,
"order_reference" => "498638"
]
);
$array2 = array(
[
"entity_id" => 1,
"order_status" => "test"
],
[
"entity_id" => 2,
"order_status" => "test"
]
);
$results = array();
array_map(function($array1, $array2) use (&$results) {
$results[] = array_merge_recursive($array1, $array2);
}, $array1, $array2);
var_dump($results);
This will output:
array (size=2)
0 =>
array (size=4)
'id' => int 220950
'order_reference' => string '600125479' (length=9)
'entity_id' => int 1
'order_status' => string 'test' (length=4)
1 =>
array (size=4)
'id' => int 220985
'order_reference' => string '498638' (length=6)
'entity_id' => int 2
'order_status' => string 'test' (length=4)
With the caveat that your arrays don't have a joint value to compare against so you need to make sure that the keys always line up, I think a loop like this will do the trick:
for ($i = 0; $i < count($array1); $i++)
{
$new_array[] = array_merge($array1[$i], $array2[$i]);
}
Edit: You can also use array_map() but it doesn't offer any performance advantages AFAIK, and is overall less readable.
$new_array = array_map(function($a1_v, $a2_v) { return array_merge($a1_v, $a2_v); }, $a1, $a2);
Use array_merge with array_map
$array1 = array(
[
"id" => 220950,
"order_reference" => "600125479"
],
[
"id" => 220985,
"order_reference" => "498638"
]
);
$array2 = array(
[
"entity_id" => 1,
"order_status" => "test"
],
[
"entity_id" => 2,
"order_status" => "test2"
]
);
$result = array_map("array_merge",$array1,$array2);
print_r($result);
Output
Array
(
[0] => Array
(
[id] => 220950
[order_reference] => 600125479
[entity_id] => 1
[order_status] => test
)
[1] => Array
(
[id] => 220985
[order_reference] => 498638
[entity_id] => 2
[order_status] => test2
)
)
Working example

Remove array entry with one or more duplicate values in multidimensional array

How can I remove an array entry with one or more duplicate values in multidimensional array? For example if I have:
array (size=4)
0 =>
array (size=3)
'food' => string 'bread' (length=5)
'color' => string 'white' (length=5)
'language' => string 'php' (length=3)
1 =>
array (size=3)
'food' => string 'rice' (length=4)
'color' => string 'purple' (length=6)
'language' => string 'c#' (length=2)
2 =>
array (size=3)
'food' => string 'pasta' (length=5)
'color' => string 'red' (length=3)
'language' => string 'php' (length=3)
3 =>
array (size=3)
'food' => string 'steak' (length=5)
'color' => string 'yellow' (length=6)
'language' => string 'ruby' (length=4)
Since there is a php entry in array[2], I want to delete the entire record so that I can have
array (size=4)
0 =>
array (size=3)
'food' => string 'bread' (length=5)
'color' => string 'white' (length=5)
'language' => string 'php' (length=3)
1 =>
array (size=3)
'food' => string 'rice' (length=4)
'color' => string 'purple' (length=6)
'language' => string 'c#' (length=2)
2 =>
array (size=3)
'food' => string 'steak' (length=5)
'color' => string 'yellow' (length=6)
'language' => string 'ruby' (length=4)
I have tried this code:
array_map("unserialize", array_unique(array_map("serialize", $array)));
and it doesn't work. What am I doing wrong?
Since your objects are all different (for instance, they all have different colors), array_unique will not reduce the number of elements.
Instead, key your array elements by their language property: that will eliminate duplicate php entries, and then convert that associated array back to an indexed one:
foreach($array as $row) {
$result[$row['language']] = $row;
}
$result = array_values($result);
The solution using array_intersect and array_merge functions (will cover duplicates for all keys):
$arr = [
['food' => 'bread', 'color' => 'white', 'language' => 'php'],
['food' => 'rice', 'color' => 'purple', 'language' => 'c#'],
['food' => 'pasta', 'color' => 'red', 'language' => 'php'],
['food' => 'steak', 'color' => 'yellow', 'language' => 'ruby']
];
$values = []; // auxiliary array
foreach ($arr as $k => $a) {
if (array_intersect($values, $a)){
unset($arr[$k]); // removing the whole `entry` if it contains duplicates in any key
} else {
$values = array_merge($values, array_values($a));
}
}
print_r($arr);
The output:
Array
(
[0] => Array
(
[food] => bread
[color] => white
[language] => php
)
[1] => Array
(
[food] => rice
[color] => purple
[language] => c#
)
[3] => Array
(
[food] => steak
[color] => yellow
[language] => ruby
)
)

How to join two arrays in php

I have two arrays called $array1 and $array2
and var_dump gives
array (size=1)
0 =>
array (size=5)
'userid' => string '8' (length=1)
'useremail' => string 'venkat#gmail' (length=12)
'username' => string 'venkatesh' (length=9)
'password' => string '1111' (length=4)
'Name' => string 'venkatesh' (length=9)
array (size=1)
'modenames' =>
array (size=3)
0 => string 'group 4' (length=7)
1 => string 'group 4' (length=7)
2 => string 'group 4' (length=7)
now i need to make a json something like this
{
"userid":"8",
"useremail":"venkat#gmail",
"username":"venkatesh",
"password":"1111",
"Name":"venkatesh",
"modenames":{"group 4","group 4","group 4"}
}
i have used array_merge() and $array1+$array2 both gives a json not in above format.. help me out.
In this case you need to,
$t = [
0 => [
'userid' => '8',
'useremail' => 'venkat#gmail',
'username' => 'venkatesh',
'password' => '1111',
'Name' => 'venkatesh'
]
];
$s = [
'modenames' => [
0 => 'group 4',
1 => 'group 4',
2 => 'group 4',
]
];
$t = $t[0] + $s;
// or
array_merge($t[0], $s);
Sum them like this and encode with JSON_FORCE_OBJECT flag:
$j = json_encode($array1[0]+$array2,JSON_FORCE_OBJECT);
Result:
{"userid":8,"useremail":"venkat#gmail","username":"venkatesh","password":"1111","Name":"venkatesh","modenames":{"0":"group4","1":"group4","2":"group4"}}
Try this
$array3 = $array1[0];
$array3['modenames'] = $array2['modenames'];
json_encode($array3);
JSON String =
{"userid":8,
"useremail":"venkat#gmail",
"username":"venkatesh",
"password":"1111",
"Name":"venkatesh",
"modenames":["group 4","group 4","group 4"]
}
As an print_r()
stdClass Object
(
[userid] => 8
[useremail] => venkat#gmail
[username] => venkatesh
[password] => 1111
[Name] => venkatesh
[modenames] => Array
(
[0] => group 4
[1] => group 4
[2] => group 4
)
)
Of course your requirement for
"modenames":{"group 4","group 4","group 4"}
cannot work as you will either need an array occurance as per my example or if you made it an object there would have to be a unique property name one for each of the 3 data items as well as the data.
try with the merge function php. if that is good for you
$array3= array_merge($array1, $array2);

Categories