Group array by values php

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



Group array by values php



I am trying to group an array by it's values. Below is my array:



I have tried below:


$result = array();
foreach ($array as $key => $record)
if (!isset($result[$record['code']]))
$result[$record['code']] = array(
'name' => $record['name'],
'age' => $record['age'],
'groups' => array(array($record['code'], $record['group'])),
);

else
$result[$record['code']]['groups'] = array($record['code'],$record['group']);


$result = array_values($result);

print_r($result);



And I am getting:



Now, I want my array to be grouped by the values of group 7777, 1000 and others(all others group values):



Thanks in advance.





What is the point of the first array level? You can have multiple "name" / "age" ?
– Mickael Leger
Aug 10 at 13:23





yes you are right.
– Ikarus
Aug 10 at 13:25





I'm right for which point? The first level is useless or you can have multiple name / age?
– Mickael Leger
Aug 10 at 13:26





I can have multiple name/age.
– Ikarus
Aug 10 at 13:30





I post an anwser that looks like what you want, but I don't get the point of adding the "code" value multiple time
– Mickael Leger
Aug 10 at 13:44




3 Answers
3



Try this :


// Create a new array
$result = array();

// Loop through your array
foreach ($array as $value)
// Create a key that start at 0
$i = 0;
// Test if $result[0] exist : if yes, you have data, else you have nothing
if (isset($result[$i]))
do
// Check if the 'name' is new : if yes, $i++ to check next name
if ($result[$i]['name'] !== $value['name']) $i++;
// If you find similar name, stop here
else break;
while (isset($result[$i]));
// Just add $result[0] with name and age value
else
$result[$i] = array (
'name' => $value['name'],
'age' => $value['age']
);

// Now you know the index of result you need to work with
// Just add a new code / group array to your code index
$result[$i][$value['group']] = array($value['code'], $value['group']);



If you do var_dump($result); the output is :


var_dump($result);


array (size=1)
0 =>
array (size=7)
'name' => string 'John Doe' (length=8)
'age' => string '36' (length=2)
1000 =>
array (size=1)
0 =>
array (size=2)
0 => string '437' (length=3)
1 => string '1000' (length=4)
7777 =>
array (size=2)
0 =>
array (size=2)
0 => string '437' (length=3)
1 => string '7777' (length=4)
1 =>
array (size=2)
0 => string '437' (length=3)
1 => string '7777' (length=4)
4000 =>
array (size=2)
0 =>
array (size=2)
0 => string '437' (length=3)
1 => string '4000' (length=4)
1 =>
array (size=2)
0 => string '437' (length=3)
1 => string '4000' (length=4)
5000 =>
array (size=1)
0 =>
array (size=2)
0 => string '437' (length=3)
1 => string '5000' (length=4)
6000 =>
array (size=2)
0 =>
array (size=2)
0 => string '437' (length=3)
1 => string '6000' (length=4)
1 =>
array (size=2)
0 => string '437' (length=3)
1 => string '6000' (length=4)



EDIT :



To get only group value equal to 7777 and 6000 replace


7777


6000


$result[$i][$value['group']] = array($value['code'], $value['group']);



by


$group_value = $value['group'] == "7777" || $value['group'] == "6000" ? $value['group'] : "Others";
$result[$i][$group_value] = array($value['code'], $value['group']);



Now the output of var_dump($result); is :


var_dump($result);


array (size=1)
0 =>
array (size=5)
'name' => string 'John Doe' (length=8)
'age' => string '36' (length=2)
'Others' =>
array (size=4)
0 =>
array (size=2)
0 => string '437' (length=3)
1 => string '1000' (length=4)
1 =>
array (size=2)
0 => string '437' (length=3)
1 => string '4000' (length=4)
2 =>
array (size=2)
0 => string '437' (length=3)
1 => string '4000' (length=4)
3 =>
array (size=2)
0 => string '437' (length=3)
1 => string '5000' (length=4)
7777 =>
array (size=2)
0 =>
array (size=2)
0 => string '437' (length=3)
1 => string '7777' (length=4)
1 =>
array (size=2)
0 => string '437' (length=3)
1 => string '7777' (length=4)
6000 =>
array (size=2)
0 =>
array (size=2)
0 => string '437' (length=3)
1 => string '6000' (length=4)
1 =>
array (size=2)
0 => string '437' (length=3)
1 => string '6000' (length=4)



Is it what you want?





Sorry, there was a typo in my question. Thanks for your quick response. :) It almost solved my problem. Actually, I want only three groups 7777, 6000 and Others. Othere will contain the group values of 1000, 4000 and 5000).
– Ikarus
Aug 10 at 14:09





7777 and 6000 are static? They won't change?
– Mickael Leger
Aug 10 at 14:12





I edited my anwser to get what you want
– Mickael Leger
Aug 10 at 14:16



I am not sure what your business logic is, but your data storage design is not optimal. Redundant levels and values can and should be removed as a matter of best practices. That advice aside, Mickael's solution will possibly let you down if your input array is not pre-sorted on code values and you have more than one code value.


code


code



The process is very straight forward. Use code values as temporary unique keys in your output array. If dealing with the first occurrence of a code value, set the name and age elements. On every iteration, add a new subarray to the output array based on the code value and the group value condition. When the loop finishes, reindex the output array with array_values().


code


code


name


age


code


group


array_values()



Code: (Demo)


$array = [
['name' => 'John Doe', 'age' => '36', 'code' => '437', 'group' => '1000'],
['name' => 'John Doe', 'age' => '36', 'code' => '437', 'group' => '7777'],
['name' => 'John Doe', 'age' => '36', 'code' => '437', 'group' => '7777'],
['name' => 'John Doe', 'age' => '36', 'code' => '437', 'group' => '4000'],
['name' => 'John Doe', 'age' => '36', 'code' => '437', 'group' => '4000'],
['name' => 'John Doe', 'age' => '36', 'code' => '437', 'group' => '5000'],
['name' => 'John Doe', 'age' => '36', 'code' => '437', 'group' => '6000'],
['name' => 'John Doe', 'age' => '36', 'code' => '437', 'group' => '6000']
];

foreach ($array as $row)
if (!isset($result[$row['code']]))
$result[$row['code']] = ['name' => $row['name'], 'age' => $row['age']];

$result[$row['code']][in_array($row['group'], ['7777','6000']) ? $row['group'] : 'others'] = [$row['code'], $row['group']];

var_export(array_values($result));



Output:


array (
0 =>
array (
'name' => 'John Doe',
'age' => '36',
'others' =>
array (
0 =>
array (
0 => '437',
1 => '1000',
),
1 =>
array (
0 => '437',
1 => '4000',
),
2 =>
array (
0 => '437',
1 => '4000',
),
3 =>
array (
0 => '437',
1 => '5000',
),
),
7777 =>
array (
0 =>
array (
0 => '437',
1 => '7777',
),
1 =>
array (
0 => '437',
1 => '7777',
),
),
6000 =>
array (
0 =>
array (
0 => '437',
1 => '6000',
),
1 =>
array (
0 => '437',
1 => '6000',
),
),
),
)



Here is one method that heavily relies on array_intersect if I may say it myself.

This is to make sure the number of loops is keept as low as possible.



I loop only the unique names, and the unique groups within that name.


$names = array_column($array, "name");
$groups = array_column($array, "group");

foreach(array_unique($names) as $name)
$intersects = array_intersect_key($array, array_intersect($names, [$name]));
$new[$name] = ["name" => $name, "age" => end($intersects)["age"]]; // Create the start of the array
foreach(array_unique($groups) as $group) // loop only unique groups
$intersects = array_intersect_key($array, array_intersect($groups, [$group])); // find matching arrays with this group
foreach($intersects as $int) $temp["group"] == "7777")
$new[$name][$group] = $temp;
else
$new[$name]["others"] = $temp;




var_dump($new);



output:


array(1)
["John Doe"]=>
array(5)
["name"]=>
string(8) "John Doe"
["age"]=>
string(2) "36"
["others"]=>
array(4)
[0]=>
array(2)
["code"]=>
string(3) "437"
["group"]=>
string(4) "1000"

[1]=>
array(2)
["code"]=>
string(3) "437"
["group"]=>
string(4) "4000"

[2]=>
array(2)
["code"]=>
string(3) "437"
["group"]=>
string(4) "4000"

[3]=>
array(2)
["code"]=>
string(3) "437"
["group"]=>
string(4) "5000"


[7777]=>
array(2)
[0]=>
array(2)
["code"]=>
string(3) "437"
["group"]=>
string(4) "7777"

[1]=>
array(2)
["code"]=>
string(3) "437"
["group"]=>
string(4) "7777"


[6000]=>
array(2)
[0]=>
array(2)
["code"]=>
string(3) "437"
["group"]=>
string(4) "6000"

[1]=>
array(2)
["code"]=>
string(3) "437"
["group"]=>
string(4) "6000"






https://3v4l.org/jCKk7



EDIT changed 1000 to 6000 as read in comments to other answer.





Again, your solution appears over-engineered and is very difficult to comprehend. All of those array_ functions are leading to lots of iteration. My stance is not about micro-optimization, it is a matter of directness and readability.
– mickmackusa
Aug 11 at 7:14


array_






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

make 2 or more post in bootsrap

Store custom data using WC_Cart add_to_cart() method in Woocommerce 3

React Native Navigation and navigating to another Screen problem