Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find all array keys that has same value

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' );
}
like image 535
micadelli Avatar asked May 11 '26 03:05

micadelli


2 Answers

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

like image 163
Paulo Freitas Avatar answered May 12 '26 18:05

Paulo Freitas


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

like image 24
Jonathan Kuhn Avatar answered May 12 '26 18:05

Jonathan Kuhn