2013-11-13 2 views
1

Есть ли более простой способ получить все ключи массива, имеющие такое же значение, когда значение неизвестно.Найти все ключи массивов, которые имеют одинаковое значение

Задача с array_unique заключается в том, что она возвращает уникальный массив и, следовательно, не находит уникальных значений.

То есть, к примеру, из этого массива:

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

Я хочу, чтобы получить эту

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

Другой способ обойти это, если бы я мог найти одинокие значения, и затем их ключи, а затем использовать array_diff

Это то, что у меня есть до сих пор, выглядит ужасно:

$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
Используя ответ Пауло Freites' в качестве базового кода, я мог бы получить его работу довольно легко, ремонтопригодны и легко на глаз вид пути ... с помощью фильтрации как метод статического класса я могу получить дублирующие значения из массива, просто вызывая 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'); 
} 
+0

что вы имеете в виду вытяжкой? Удалить дубликаты? сохранить только дубликаты? –

+0

Угадайте, что он означает создать новый массив с одинаковыми элементами, сохраняя свои исходные ключи, как в примере. – Wh1T3h4Ck5

+0

Мне не нужен начальный массив, так что либо я хочу иметь уникальные ключи, либо ключи с дубликатами .. и по уникальному я имею в виду, что значение этого ключа больше не существует в массиве – micadelli

ответ

3

Воспользовавшись затворов для более прямого решения:

$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); 

Это дало мне следующее:

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

Демо: https://eval.in/67526

Это все! :)

Update: обратная совместимость решение

$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); 

Демо: https://eval.in/68255

+0

хороший. Разве это не работает только в PHP 5.3 и выше? Сервер имеет 5.2.4 – micadelli

+0

@micadelli К сожалению, да! Я обновил свой ответ с помощью обратного решения, которое вместо закрытия закрывает ('create_function()'] (http://www.php.net/create_function). :) –

+0

интересный материал, который 'create_function'. К сожалению, он имеет * плохую производительность и характеристики использования памяти * ... Как-то, исходя из JavaScript, мне нравится держаться подальше от какого-либо злого кода 'eval' :) Я попытаюсь развернуть свой код, используя вместо этого метод статического класса и посмотреть, как это работает. – micadelli

1

на данный момент я не могу понять другое решение ...

// 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)); 

выход:

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

) 

пример # 2: - когда умножились различные значения

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

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

выход:

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

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

) 

если результат функции присвоен до $res переменная $res[0] получает массив из всех элементов из исходного массива с первым значением, найденным более одного раза, $res[1] получает массив элементов с другой функцией duplicated-value и т. Д. Возвращает false, если в аргументе-массиве ничего не найдено.

+0

обновлено ... я не знаю значения. значение «дублирующее значение» – micadelli

+0

ах, вы хотите сначала совместить повторяющиеся значения, а затем вытащить элементы. – Wh1T3h4Ck5

+0

Правильно ... это то, что делает мой скрипт, но я думал, что это может быть достигнуто более простым способом – micadelli

1

Если вы хотите, чтобы получить дубликаты в массиве, попробуйте следующее:

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

Я нашел это из:

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

+0

этот метод возвращает ключ/значение, в котором есть дубликаты – micadelli

+0

А, хорошо, непонимание. – SamV

+0

@micadelli Я нашел хороший небольшой фрагмент из раздела комментариев ниже в php-документах 'array_unique', надеюсь, что это поможет. – SamV

2

Ваша реализация имеет несколько проблем.

1) Если есть 2 значения 1000 и 2 другого значения, array_flip потеряет один из наборов значений.

2) Если существует более двух разных значений, то массивы array_keys найдут только одно значение, которое больше всего встречается.

3) Если дубликатов нет, вы все равно вернете одно из значений.

Нечто подобное всегда работает и возвращает все повторяющиеся значения:

<?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

1

Попробуйте

$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); 
+0

извините, чувак, не упомянул, что эти значения случайны, только поставить 1 против 1000 для удобочитаемости – micadelli

+0

Я отредактировал код, извините. Посмотрите, работает ли это для вас. @micadelli – abfurlan

Смежные вопросы