Find all array keys that has same value

19,118

Solution 1

Taking advantage of closures for a more straightforward solution:

$array = array('a' => 1000, 'b' => 1, 'c' => 1000);
$counts = array_count_values($array);
$filtered = array_filter($array, function ($value) use ($counts) {
    return $counts[$value] > 1;
});
var_dump($filtered);

This gave me the following:

array(2) {
  ["a"]=>
  int(1000)
  ["c"]=>
  int(1000)
}

Demo: https://eval.in/67526

That's all! :)

Update: backward-compatible solution

$array = array('a' => 1000, 'b' => 1, 'c' => 1000);
$counts = array_count_values($array);
$filtered = array_filter($array, create_function('$value',
    'global $counts; return $counts[$value] > 1;'));
var_dump($filtered);

Demo: https://eval.in/68255

Solution 2

Your implementation has a few issues.

1) If there are 2 of value 1000 and 2 of another value, the array_flip will lose one of the sets of values.

2) If there are more than two different values, the array_keys will only find the one value that occurs most.

3) If there are no duplicates, you will still bring back one of the values.

Something like this works always and will return all duplicate values:

<?php
//the array
$a = array( 'a' => 1000, 'b' => 1, 'c' => 1000 );
//count of values
$cnt = array_count_values($a);

//a new array
$newArray = array();
//loop over existing array
foreach($a as $k=>$v){
    //if the count for this value is more than 1 (meaning value has a duplicate)
    if($cnt[$v] > 1){
        //add to the new array
        $newArray[$k] = $v;
    }
}

print_r($newArray);

http://codepad.viper-7.com/fal5Yz

Solution 3

at the moment I cant figure out another solution...

  // target array
  $your_array = array('a'=>1000, 'b'=>1, 'c'=>1000);

  // function to do all the job
  function get_duplicate_elements($array) {
    $res = array();
    $counts = array_count_values($array);
    foreach ($counts as $id=>$count) {
     if ($count > 1) {
       $r = array();
       $keys = array_keys($array, $id);
       foreach ($keys as $k) $r[$k] = $id;
       $res[] = $r;
       }
     }
    return sizeof($res) > 0 ? $res : false;
    }

  // test it
  print_r(get_duplicate_elements($your_array));

output:

Array
(
    [0] => Array
        (
            [a] => 1000
            [c] => 1000
        )

)

example #2: - when you have different values multiplied

// target array
$your_array = array('a'=>1000, 'b'=>1, 'c'=>1000, 'd'=>500, 'e'=>1);

// output
print_r(get_duplicate_elements($your_array));

output:

Array
(
    [0] => Array
        (
            [a] => 1000
            [c] => 1000
        )

    [1] => Array
        (
            [b] => 1
            [e] => 1
        )

)

if function result has been assigned to $res variable $res[0] gets an array of all elements from original array with first value found more than once, $res[1] gets array of elements with another duplicated-value, etc... function returns false if nothing duplicate has been found in argument-array.

Solution 4

If you want to get the duplicates in an array try this:

array_unique(array_diff_assoc($array1, array_unique($array1)))

I found this from:

http://www.php.net/manual/en/function.array-unique.php#95203

Solution 5

Try this

$a = array( 'a' => 1, 'b' => 1000, 'c' => 1000,'d'=>'duplicate','e'=>'duplicate','f'=>'ok','g'=>'ok' );
$b = array_map("unserialize", array_unique(array_map("serialize", $a)));
$c = array_diff_key($a, $b);
Share:
19,118
micadelli
Author by

micadelli

Updated on June 04, 2022

Comments

  • micadelli
    micadelli almost 2 years

    Is there a simpler way to get all array keys that has same value, when the value is unknown.

    The problem with array_unique is that it returns the unique array and thus it doesn't find unique values.

    That is, for example, from this array:

    Array (
      [a]=>1000
      [b]=>1
      [c]=>1000
    )
    

    I want to get this

    Array (
      [a]=>1000
      [c]=>1000
    )
    

    Another way around this is, if I could find the lonely values, and then their keys, and then use array_diff

    This is what I've got so far, looks awful:

    $a = array( 'a' => 1000, 'b' => 1, 'c' => 1000 );
    $b = array_flip( array_count_values( $a ) );
    krsort( $b );
    $final = array_keys( $a, array_shift( $b ) );
    

    Update
    Using Paulo Freites' answer as a code base, I could get it working pretty easily, maintainable and easy on eyes kind of way… by using the filtering as a static class method I can get the duplicate values from an array by just calling ClassName::get_duplicates($array_to_filter)

    private static $counts = null;
    
    private static function filter_duplicates ($value) {
        return self::$counts[ $value ] > 1;
    }
    
    public static function get_duplicates ($array) {
        self::$counts = array_count_values( $array );
        return array_filter( $array, 'ClassName::filter_duplicates' );
    }
    
  • micadelli
    micadelli over 10 years
    that method returns the key/value that has the duplicates itself
  • micadelli
    micadelli over 10 years
    updated… i don't know the value. the value is "duplicate value"
  • Wh1T3h4Ck5
    Wh1T3h4Ck5 over 10 years
    ah, you want to match duplicate values first then to pull elements out.
  • SamV
    SamV over 10 years
    Ah, okay misunderstanding.
  • micadelli
    micadelli over 10 years
    correct… that's what my script does, but i thought it could be achieved way more simpler
  • SamV
    SamV over 10 years
    @micadelli I found a nice little snippet from the comments section below in the array_unique php docs, hope that helps.
  • Wh1T3h4Ck5
    Wh1T3h4Ck5 over 10 years
    it now works, even if you have more different values duplicated in an array.
  • micadelli
    micadelli over 10 years
    sorry, dude, didn't mention that those values are random, only put 1 vs 1000 for readability
  • micadelli
    micadelli over 10 years
    nice one. Isn't this working only in PHP 5.3 and above? The server has 5.2.4
  • user222758
    user222758 over 10 years
    @micadelli Unfortunately yes! I've updated my answer with a backward-compatible solution which uses create_function() in place of closures. :)
  • micadelli
    micadelli over 10 years
    interesting stuff, that create_function. Unfortunately thought, it has bad performance and memory usage characteristics… Somehow coming from JavaScript side, I like to stay away from any evil eval kind of code :) I'll try to fork your code using a static class method instead and see how it works.
  • user222758
    user222758 over 10 years
    @micadelli Yea, create_function() it's not so bad, but have disadvantages in place of closures... You can get more info about that difference here: stackoverflow.com/q/6485336/222758 Unfortunately, the only other way to achieve that with array_filter() is the way you've switched for, using classes. It's not so bad either... Glad to know that I was able to help you! :)
  • abfurlan
    abfurlan over 10 years
    I edited the code, sorry. See if it works for you. @micadelli