Group Duplicate Array Keys in a Multidimensional Array into Subarray

Group duplicate array keys in a multidimensional array into subarray

This should do it, it's not exactly what you want but I don't see a reason why you'd need to index the resulting array numerically, and then by artist.

$source = array(
array('Michael Jackson' => 'Thriller'),
array('Michael Jackson' => 'Rock With You'),
array('Teddy Pendergrass' => 'Love TKO'),
array( 'ACDC' => 'Back in Black')
);

$result = array();

foreach($source as $item) {
$artist = key($item);
$album = current($item);

if(!isset($result[$artist])) {
$result[$artist] = array();
}
$result[$artist][] = $album;
}

And you can loop the $result array and build your HTML like this:

foreach($result as $artist => $albums) {
echo '<h2>'.$artist.'</h2>';
echo '<ul>';
foreach($albums as $album) {
echo '<li>'.$album.'</li>';
}
echo '</ul>';
}

Which would result in a similar list that you described.

PHP multidimensional array: group repeated values and create sub array

Nothing wrong with the code you've provided at the end, but here's some ideas for how to make it more tolerant to more array values (as you mentioned, phone, email, etc).

This uses the handy PHP array_diff_key function to remove the array elements you don't want from the "core" records. Then, applying array_diff_key to get those same array elements INTO the "company" records.

// set up the array of keys you don't want in the "original" record
$exclude = ['company' => FALSE, 'price' => FALSE];
// Your original loop
foreach($array as $v) {
// not strictly necessary, but helps readability
$id = $v['id'];
// Assign the "core" record all the values you want, excluding those defined above
// in this case, will remove "company" and "price"
$record = array_diff_key( $v, $exclude );

// only set this if not already set, otherwise wipes out previous companies
if ( ! isset($result[$id] ) ) {
$result[$id] = $record;
$result[$id]['companies'] = [];
}

// strip off the OTHER values from the array you don't want stored with the company
// this will automatically pick up the field NOT excluded above
// in this case, will remove all BUT "company" and "price"
$company = array_diff_key( $v, $record );
$result[$id]['companies'][] = $company;
}

Group arrays according to their keys and remove duplicates (2 dimensional arrays)

You can use array_map() for group according to keys:

$a = array('member0','member1','member2','member1');
$b = array('id0','id1','id2','id1');
$c = array('tf0','tf1','tf2','tf1');

$merge = array_map(function($a1, $b1, $c1){
return array($a1, $b1, $c1);
}, $a, $b, $c);

For removing duplicate records you can use array_map() and array_unique():

// remove duplicates by using array_map() and `array_unique()` for multidimensional array
$duplicateRemoved = array_map("unserialize", array_unique(array_map("serialize", $merge)));

// rearrange the array
$rearrangeArray = array_values($duplicateRemoved);

echo "<pre>";
print_r($rearrangeArray);

Result:

Array
(
[0] => Array
(
[0] => member0
[1] => id0
[2] => tf0
)

[1] => Array
(
[0] => member1
[1] => id1
[2] => tf1
)

[2] => Array
(
[0] => member2
[1] => id2
[2] => tf2
)

)

Multi-dimensional array return keys with duplicate values

Edit: I've updated the answer quite a bit.

Edit 2: Now utilizing the built in array functions to find the duplicates

$products = [
0 => ['product-id' => 124],
1 => ['product-id' => 125],
2 => ['product-id' => 124],
3 => ['product-id' => 126],
4 => ['product-id' => 126],
8 => ['product-id' => 124],
];

// Find the duplicates
$product_ids = array_column($products, 'product-id');
$count = array_count_values($product_ids);
$duplicates = array_filter($count, function($var) {
return $var > 1;
});

// List all the entries with duplicate ids:
foreach ( array_flip($duplicates) as $product_id ) {
$filter = array_filter($products, function($var) use ($product_id) {
return ( $var['product-id'] === $product_id );
});
print_r('Product-id: ' . $product_id . ' is duplicated in entries: ');
print_r(array_keys($filter));
}

The output:

// Product-id: 124 is duplicated in entries: Array
// (
// [0] => 0
// [1] => 2
// [2] => 8
// )
// Product-id: 126 is duplicated in entries: Array
// (
// [0] => 3
// [1] => 4
// )

Group rows by one column, only create deeper subarrays when multiple rows in group

Try,

$arr = array( array('id'=>1, 'email_id'=>'ok@gmail.com', 'password'=>'test'),
array('id'=>2, 'email_id'=>'check@gmail.com', 'password'=>'test'),
array('id'=>3, 'email_id'=>'an@gmail.com', 'password'=>'pass'));

$new_arr = array();
foreach($arr as $k => $v) {
if( is_array($arr[$k+1]) && $arr[$k]['password'] === $arr[$k + 1]['password'] )
$new_arr[] = array($arr[$k], $arr[$k+1]);
else if( in_array_recursive($arr[$k]['password'], $new_arr) === FALSE )
$new_arr[] = $v;
}

function in_array_recursive( $val, $arr) {
foreach( $arr as $v ) {
foreach($v as $m) {
if( in_array($val, $m ) )
return TRUE;
}
}
return FALSE;
}

print_r($new_arr);

Demo

How to group keys and values of an (sub)array and sum its values using PHP?

I'm surprised at all the long and complicated answers. However, the initial foreach to model your data to something manageable is needed. After that you just need to do a really simple array_walk.

<?php
$result = array();
foreach ($array as $el) {
if (!array_key_exists($el[0], $result)) {
$result[$el[0]] = array();
}
$result[$el[0]][] = $el[1];
}
array_walk($result, create_function('&$v,$k', '$v = array_sum($v) / count($v);'));
?>

Result:

Array
(
[ALFA] => 187
[BETA] => 167
[ZETA] => 254
[GAMA] => 175.5
)

Group and merge subarray data based on one column value

A simple loop should do this..

$group = [];
foreach ($data as $item) {
if (!isset($group[$item['date']])) {
$group[$item['date']] = [];
}
foreach ($item as $key => $value) {
if ($key == 'date') continue;
$group[$item['date']][$key] = $value;
}
}

Group rows of data, maintain a subarray of ids within the group, and only present the lowest id in each group as the first level key

One way to do it is to group by first name and last name, and then reverse the grouping to get a single id. krsort the input beforehand to make sure you get the lowest id.

krsort($input);

//group
foreach ($input as $id => $person) {
// overwrite the id each time, but since the input is sorted by id in descending order,
// the last one will be the lowest id
$names[$person['lastName']][$person['firstName']] = $id;
}

// ungroup to get the result
foreach ($names as $lastName => $firstNames) {
foreach ($firstNames as $firstName => $id) {
$result[$id] = ['firstName' => $firstName, 'lastName' => $lastName];
}
}

Edit: not too much different based on your updated question. Just keep all the ids instead of a single one.

krsort($input);

foreach ($input as $id => $person) {
// append instead of overwrite ↓
$names[$person['lastName']][$person['firstName']][] = $id;
}
foreach ($names as $lastName => $firstNames) {
foreach ($firstNames as $firstName => $ids) {
// $ids is already in descending order based on the initial krsort
$id = array_pop($ids); // removes the last (lowest) id and returns it
$result[$id] = [
'firstName' => $firstName,
'lastName' => $lastName,
'merged_with' => implode(',', $ids)
];
}
}

Use subarray keys to form new first level keys to group values

You were in the right direction, you just needed the [] in front of $key to achieve your desired result, as shown below:

$samearray = array();
foreach ($a as $det) {
foreach ($det as $key => $det1) {
$samearray[$key][] = $det1;
}
}

print_r($samearray);


Related Topics



Leave a reply



Submit