1

I'm trying to count and remove duplicate arrays. To be a duplicate the entire array would have the match in keys and values with another.

Array
(
    [0] => Array
        (
            [name] => Superman
            [time] => 60 
        )

    [1] => Array
        (
            [name] => Superman
            [time] => 60
        )

    [2] => Array
        (
            [name] => Superman
            [time] => 50
        )

    [3] => Array
        (
            [name] => Superman
            [time] => 40
        )

    [4] => Array
        (
            [name] => Superman
            [time] => 50
        )

    [5] => Array
        (
            [name] => Superman
            [time] => 60
        )

)

Into:

Array
(
    [0] => Array
        (
            [name] => Superman
            [time] => 60
            [count] => 3
        )

    [1] => Array
        (
            [name] => Superman
            [time] => 50
            [count] => 2
        )

    [2] => Array
        (
            [name] => Superman
            [time] => 40
        )

)

I've come across this answer that can remove the duplicates, but I'm struggling to see how I may count them.

$input = array_map("unserialize", array_unique(array_map("serialize", $input)));
Community
  • 1
  • 1
ditto
  • 5,917
  • 10
  • 51
  • 88

4 Answers4

2

Quick and dirty, but you get exactly the data structure you asked for:

$data = array(
    array("name" => "Superman", "time" => 60),
    array("name" => "Superman", "time" => 60),
    array("name" => "Superman", "time" => 50),
    array("name" => "Superman", "time" => 40),
    array("name" => "Superman", "time" => 50),
    array("name" => "Superman", "time" => 60),
);

// count the occurrences
$occurrences = array();
for ($i = 0, $l = count($data); $i < $l; $i++) {
    $serialized = serialize($data[$i]);
    if (!isset($occurrences[$serialized])) {
        $occurrences[$serialized] = 1;
    }
    else {
        $occurrences[$serialized] = $occurrences[$serialized] + 1;
    }
}

// get the wanted structure
$uniques = array();
foreach ($occurrences as $serialized => $count) {
    $unserialized = unserialize($serialized);
    if ($count > 1) {
        $unserialized['count'] = $count;
    }
    $uniques[] = $unserialized;
}

print_r($uniques);
1

You can use array_count_values in this case too. Example:

$values = array(
    array('name' => 'Superman', 'time' => 60),
    array('name' => 'Superman', 'time' => 60),
    array('name' => 'Superman', 'time' => 50),
    array('name' => 'Superman', 'time' => 40),
    array('name' => 'Superman', 'time' => 50),
    array('name' => 'Superman', 'time' => 60),
);

// map out into string then unique them
$uniques = array_map("unserialize", array_unique(array_map("serialize", $values)));
$count = array_count_values(array_map("serialize", $values)); // map out the arrays then get the counts

// then to merge the count
foreach($uniques as &$batch) {
    foreach($count as $array => $v) {
        if(unserialize($array) == $batch) { // if this particular key count is equal to this unique array, then push the count
            $batch['count'] = $v;
        }
    }
}

echo '<pre>';
print_r($uniques);

Sample Output

Kevin
  • 41,694
  • 12
  • 53
  • 70
1

Not as compact as I would like, but it gets the job done:

function unserialize_unique_count($input, $k = 'count') {
    $a = [];
    foreach ($input as $d) {
        $s = serialize($d);
        $a[$s] = (isset($a[$s]) ? ($a[$s] + 1) : 1);
    }
    foreach ($a as $s => $c) {
        $a[$s] = unserialize($s) + [ $k => $c ];
    }
    return array_values($a);
}

$grouped_with_count = unserialize_unique_count($input);

How it works: The first loop serializes and counts. The second unique merges. O(n).

How to use: Pass your multi-dimensional array as argument #1. Gives you back uniques with an additional key "count" that holds the count. If you want the count key to be something other than "count", pass the function a second argument.

bishop
  • 37,830
  • 11
  • 104
  • 139
  • In your example output, if the count is one, there is no "count" key. I've not handled that scenario. If you need, replace the unserialize line with: `$a[$s] = unserialize($s) + (1 < $c ? [ $k => $c ] : []);` – bishop Sep 11 '14 at 14:19
0
  1. Get Array and its values
  2. make unique key on paypal_address
  3. Use unique key to create temp array
  4. Store all values with respective unique key in temp array
  5. I am using time as unique key.

     $tmpArr = Array();
    $cnt = sizeof($arr);
    for($i=0;$i<$cnt;$i++){
            $time = $arr[$i]['time'];
            if(!is_array($tmpArr[$time])){
                    $tmpArr[$time] = Array();
                    $tmpArr[$time]['count'] = 0;
            }
            $tmpArr[$time]['time'] = $arr[$i]['time'];
            $tmpArr[$time]['name'] = $arr[$i]['name'];
            $tmpArr[$time]['count'] = $tmpArr[$time]['count'] + 1;
    
    }
    print_r($tmpArr);
    

Note: Make changes in code according to your requirement

Rajesh Ujade
  • 2,715
  • 19
  • 39