Get the keys for duplicate values in an array

35,864

Solution 1

function get_keys_for_duplicate_values($my_arr, $clean = false) {
    if ($clean) {
        return array_unique($my_arr);
    }

    $dups = $new_arr = array();
    foreach ($my_arr as $key => $val) {
      if (!isset($new_arr[$val])) {
         $new_arr[$val] = $key;
      } else {
        if (isset($dups[$val])) {
           $dups[$val][] = $key;
        } else {
           $dups[$val] = array($key);
           // Comment out the previous line, and uncomment the following line to
           // include the initial key in the dups array.
           // $dups[$val] = array($new_arr[$val], $key);
        }
      }
    }
    return $dups;
}

obviously the function name is a bit long;)

Now $dups will contain a multidimensional array keyed by the duplicate value, containing each key that was a duplicate, and if you send "true" as your second argument it will return the original array without the duplicate values.

Alternately you could pass the original array as a reference and it would adjust it accordingly while returning your duplicate array

Solution 2

I'll answer the second question first. You want to use array_keys with the "search_value" specified.

$keys = array_keys($array, "2011-06-29")

In the example below, $duplicates will contain the duplication values while $result will contain ones that are not duplicates. To get the keys, simply use array_keys.

<?php

$array = array(
  'a',
  'a',
  'b',
  'c',
  'd'
);

// Unique values
$unique = array_unique($array);

// Duplicates
$duplicates = array_diff_assoc($array, $unique);

// Unique values
$result = array_diff($unique, $duplicates);

// Get the unique keys
$unique_keys = array_keys($result);

// Get duplicate keys
$duplicate_keys = array_keys(array_intersect($array, $duplicates));

Result:

// $duplicates
Array
(
    [1] => a
)

// $result
Array
(
    [2] => b
    [3] => c
    [4] => d
)

// $unique_keys
Array
(
    [0] => 2
    [1] => 3
    [2] => 4
)

// $duplicate_keys
Array
(
    [0] => 0
    [1] => 1
)

Solution 3

I had a similar problem as question #1 from the OP. All I needed were the keys for duplicate values in my original array. Here's what I came up with:

$array = array('yellow', 'red', 'green', 'brown', 'red', 'brown');

$counts = array_count_values($array);
$filtered = array_filter($counts, function($value) {
    return $value != 1;
});
$result = array_keys(array_intersect($array, array_keys($filtered)));

And for the output:

print_r($result);
Array
(
    [0] => 1
    [1] => 3
    [2] => 4
    [3] => 5
)

Solution 4

$array = array(0 => "1", 1 => "1", 2 => "2", 3 => "3");
$count = array();
foreach($array as $key => $value) {
  if(!isset($count[$value])) {
    $count[$value] = 0;
  }
  $count[$value]++;
}


$result = array_filter($count, function($value) {
  return $value > 1;
});

$result = array_keys($result);

var_dump($result);

Output

array(1) {
  [0]=>
  int(1)
}

Solution 5

here is a code dude

   $your_array = array(0 => '2011-06-21', 1 => '2011-06-22', 2 => '2011-06-22', 3 => '2011-06-23', 4 =>
'2011-06-23', 5 => '2011-06-24', 6 => '2011-06-24', 7 => '2011-06-25', 8 => '2011-06-25', 9 
=> '2011-06-26', 10 => '2011-06-26', 11 => '2011-06-27', 12 => '2011-06-27', 13 => '2011-06-  
28', 14 => '2011-06-29', 15 => '2011-06-29', 16 => '2011-06-30', 17 => '2011-06-30', 18 => 
'2011-07-01', 19 => '2011-07-01', 20 => '2011-07-02', 21 => '2011-07-02', 22 => '2011-07-03', 
23 => '2011-07-03', 24 => '2011-07-04', 25 => '2011-07-04', 26 => '2011-07-05', 27 => '2011-
07-05', 28 => '2011-07-06', 29 => '2011-07-06', 30 => '2011-07-07', 31 => '2011-07-07');

$keys_of_duplicated = array();
$array_keys = array();

foreach($your_array as $key => $value) {
    //- get the keys of the actual value
    $array_keys = array_keys($your_array, $value);

    //- if there is more then one key collected we register it
    if(count($array_keys) > 1) {
        //- foreach key that have the same value we check if i'ts already registered
        foreach($array_keys as $key_registered) {
            //- if not registered we register it
            if(!in_array($key_registered,  $keys_of_duplicated)) {
                 $keys_of_duplicated[] = $key_registered;
            }
        }
    }
}

var_dump($keys_of_duplicated);

$keys_of_duplicated is now the array that contains the keys of duplicated arrays ;) bye

Share:
35,864
schaitanya
Author by

schaitanya

SOreadytohelp

Updated on July 09, 2022

Comments

  • schaitanya
    schaitanya almost 2 years

    I have the following array:

    $myarray = Array("2011-06-21", "2011-06-22", "2011-06-22", "2011-06-23", "2011-06-23", "2011-06-24", "2011-06-24", "2011-06-25", "2011-06-25", "2011-06-26");
    var_dump($myarray);
    

    Result:

    Array (
        [0] => 2011-06-21
        [1] => 2011-06-22
        [2] => 2011-06-22
        [3] => 2011-06-23
        [4] => 2011-06-23
        [5] => 2011-06-24
        [6] => 2011-06-24
        [7] => 2011-06-25
        [8] => 2011-06-25
        [9] => 2011-06-26
    )
    
    1. Now how can I display the keys with duplicate values? Here the function should NOT return ([0],[9]) since there are no duplicates with the values.
    2. How to find the keys for the same value, eg. for "2011-06-25" it should return [7],[8]
  • cypher
    cypher almost 13 years
    This will return values, not keys.
  • Francois Deschenes
    Francois Deschenes almost 13 years
    @cypher - You're right. I forgot to include array_keys. I've updated my answer.
  • cypher
    cypher almost 13 years
    Also, interesting question would be if he wanted to print out all the duplicate keys - in your case 0 and 1 for a
  • Francois Deschenes
    Francois Deschenes almost 13 years
    @cypher - A simple array_keys(array_intersect($array, $duplicates)) would do just that. :)
  • Dereleased
    Dereleased almost 13 years
    you could shorten the code path when $clean === true by putting if ($clean === true) { return array_unique($my_arr); } at the top ;)
  • hakre
    hakre almost 13 years
    +1 Nice answer. I like the unique / diff approach. But OP asked not for the unique, but those keys that are not unique. So probably you should not only put that into comment but into your answer as well.
  • Dereleased
    Dereleased almost 13 years
    In my testing, this times out (60 seconds) on a sufficiently large array (100,000 in my test).
  • Dereleased
    Dereleased almost 13 years
    By the way, fastest method I've tested so far, handles 100 iterations of an 100,000+ element array in approx 0.04463 seconds per iteration!
  • Dereleased
    Dereleased almost 13 years
    This is only really useful on small arrays -- the larger the array, the more that iterating over it several times and running these comparisons is going to hurt. Really fast for small enough sets, though =)
  • Dereleased
    Dereleased almost 13 years
    Changed my testing methodology a bit and while still fastest, actual iteration time is closer to 0.1811 seconds; the array had (on average) 165,000 elements, 100,000 of which were unique.
  • Alex2php
    Alex2php about 10 years
    Maybe this was not the intention of the function but this function returns non-duplicate values too. Just wanted to mention this. I did a foreach ($dups as $k=>$v) { if( count($v) == 1) unset($dups[$k]); } to fix this but I think this not very effective.
  • Trey
    Trey about 10 years
    Oops, there was a logic problem, it should have been if(!isset($new_arr[$val])), I fixed it and it should work as expected now
  • xxstevenxo
    xxstevenxo almost 8 years
    In the instance that you would like to also know the number of "pairs" within the duplicates you could also use count(array_unique($duplicates)); so if you duplicates array was ("a","b","a","b") this would return 2
  • goron
    goron almost 8 years
    Maybe this is intentional, but this function doesn't return all the keys that have duplicate values. It returns only the keys after the first one found. I see how that could be intentional (you could consider only the later ones "duplicates"), but it was confusing to me. I expected it to return all keys that had values that other keys also had.
  • Trey
    Trey almost 8 years
    @goron That was the intention, but I definitely see how it would be useful to have either option, so I've updated with a comment to basically make this function act as you expected.
  • Faisal Sheikh
    Faisal Sheikh almost 5 years
    @Trey Thank you so much! you made my day.