5

I need to count the same values in multidimensional array and remove duplicates

My array now

[0] => Array
    (
        [id] => 1
        [title] => BMW
    )

[1] => Array
    (
        [id] => 1
        [title] => BMW
    )

[2] => Array
    (
        [id] => 2
        [title] => Mercedes
    )       
.......

Need to output

[0] => Array
    (
        [id] => 1
        [title] => BMW
        [count] => 2
    )

[1] => Array
    (
        [id] => 2
        [title] => Mercedes
        [count] => 1
    )       

I will be very grateful for your help

Dizzy
  • 47
  • 1
  • 2

4 Answers4

4

The key problem is that an array(that with an id and a title) is not hashable.

So we can try to hash it, just join them all together, and make the result string as a hash key.

So, we maintain a hash table, which key is the object hash key, and the value is the result array index.

And then, For each item we travel, we can find the result array position by the help of the hash table, and then add the count.

Here's my code.

<?php

$array_in = array(
    array('id'=>1, 'title'=>'BMW'),
    array('id'=>1, 'title'=>'BMW'),
    array('id'=>2, 'title'=>'Mercedes'),
);

$hash = array();
$array_out = array();

foreach($array_in as $item) {
    $hash_key = $item['id'].'|'.$item['title'];
    if(!array_key_exists($hash_key, $hash)) {
        $hash[$hash_key] = sizeof($array_out);
        array_push($array_out, array(
            'id' => $item['id'],
            'title' => $item['title'],
            'count' => 0,
        ));
    }
    $array_out[$hash[$hash_key]]['count'] += 1;
}

var_dump($array_out);
Alfred Huang
  • 17,654
  • 32
  • 118
  • 189
2

In this sample I've used array_reduce to build a second array out of appropriate elements from your first array. Due to the way that I check for duplicate values, this assumes that your initial array is sorted (all the dupes are next to each other).

function dedupe($carry, $item) {
    // check if array is non empty, and the last item matches this item
    if (count($carry) > 0 
        && $carry[count($carry) - 1][0] == $item[0] 
        && $carry[count($carry) - 1][1] == $item[1]) {

        // the array contains a match, increment counter
        $carry[count($carry) - 1][2]++;
    } else {
        // there was no match, add element to array
        $carry[] = array($item[0], $item[1], 1);
    }
    return $carry;
}

$cars = array(
    array(1, "BMW"),
    array(1, "BMW"),
    array(2, "Mercedes")
);

$uniques = array_reduce($cars, "dedupe", array());

var_dump($uniques);
James
  • 20,957
  • 5
  • 26
  • 41
2

You can iterate over the array and construct the final array following this pattern:

If a key with the id of the element exists in the final array, update its counter.

If it doesn't, create a new element with its id as key.

$orig = array(
    array('id' => 1, 'title' => 'BMW'),
    array('id' => 1, 'title' => 'BMW'),
    array('id' => 2, 'title' => 'Mercedes'),
);

$result = array();
foreach ($orig as $element) {
    (isset($result[$element["id"]])) ?
                    $result[$element["id"]]["count"] += 1 :
                    $result[$element["id"]] = array("id" => $element["id"], "title" => $element["title"], "count" => 1);
}
print_r($result);
acontell
  • 6,792
  • 1
  • 19
  • 32
2
$cars = array(
    array('id'=>1, 'title'=>'BMW'),
    array('id'=>1, 'title'=>'BMW'),
    array('id'=>2, 'title'=>'Mercedes'),
);

$serialize = array_map("serialize", $cars);
$count     = array_count_values ($serialize);
$unique    = array_unique($serialize);

foreach($unique as &$u)
{
    $u_count = $count[$u];
    $u = unserialize($u);
    $u['count'] = $u_count;
}

print_r($unique);

Else if the count is not necessary you can simply follow this example:

$result = array_map("unserialize", array_unique(array_map("serialize", $array_in)));

Community
  • 1
  • 1
Anthony Raimondo
  • 1,621
  • 2
  • 24
  • 40