从数组中删除重复项(按键数组唯一化)

15
Array
(
    [0] => Array
        (
            [file] => /var/websites/example.com/assets/images/200px/1419050406e6648e1c766551a0ffc91380fd6ff3406002011-10-233750.jpg
            [md5] => 42479bee7a304d2318250de2ef1962a9
            [url] => http://example.com/assets/images/200px/1419050406e6648e1c766551a0ffc91380fd6ff3406002011-10-233750.jpg
        )

    [1] => Array
        (
            [file] => /var/websites/example.com/assets/images/200px/21277792606e6648e1c766551a0ffc91380fd6ff3406002011-10-233750.jpg
            [md5] => 42479bee7a304d2318250de2ef1962a9
            [url] => http://example.com/assets/images/200px/21277792606e6648e1c766551a0ffc91380fd6ff3406002011-10-233750.jpg
        )
)

我该如何从以上数组中去除MD5键的重复项?


2
你是想要删除仅包含MD5密钥的元素,还是整个包含重复密钥的数组? - ariefbayu
通用数组还是特定于某种语言? - Tim
@Tim,从标签来看,我认为这是关于PHP的。 - ariefbayu
8个回答

17
<?php
$data = array(
  array(
    'md5' => 'alpha',
    'some' => 'value',
  ),
  array(
    'md5' => 'alpha',
    'some' => 'other value',
  ),
  array(
    'md5' => 'bravo',
    'some' => 'third value',
  ),
);
// walk input array
$_data = array();
foreach ($data as $v) {
  if (isset($_data[$v['md5']])) {
    // found duplicate
    continue;
  }
  // remember unique item
  $_data[$v['md5']] = $v;
}
// if you need a zero-based array, otheriwse work with $_data
$data = array_values($_data);

不客气。您能否标记一下您的问题已经得到回答了呢?(无所谓哪个回答……Gumbo的也很好……) - rodneyrehm

7

在你们的帮助下,这是我的最终函数...希望它能帮助未来的某个人...

    $data = array(
          array(
            'md5' => 'alpha',
            'some' => 'value',
          ),
          array(
            'md5' => 'alpha',
            'some' => 'other value',
          ),
          array(
            'md5' => 'bravo',
            'some' => 'third value',
          ),
        );
        // walk input array


        function remove_duplicateKeys($key,$data){

        $_data = array();

        foreach ($data as $v) {
          if (isset($_data[$v[$key]])) {
            // found duplicate
            continue;
          }
          // remember unique item
          $_data[$v[$key]] = $v;
        }
        // if you need a zero-based array
        // otherwise work with $_data
        $data = array_values($_data);
        return $data;
        }

$my_array = remove_duplicateKeys("md5",$data);

这很好,但我如何添加嵌套键呢?比如说在“some”里面有“name”,现在我该如何避免在["some"]["name"]中出现重复? - radren

6
PHP已经有一个函数可以删除数组中的重复元素。但不幸的是,array_unique仅支持基于字符串的比较:

注意: 仅当 (string) $elem1 === (string) $elem2 时,两个元素才被视为相等。换句话说:当字符串表示相同时。第一个元素将被使用。

问题在于任何转换为字符串的数组都等于任何其他数组:

数组总是转换为字符串“Array”;[...]

但是您可以使用数组键的唯一性来解决这个问题:
$index = array();
foreach ($arr as $key => $item) {
    if (isset($index[$item['md5']])) {
        unset($item[$key]);
    }
    $index[$item['md5']] = TRUE;
}

我认为你的意思是使用$item['md5']而不是$arr['md5'] - middus

3
由于 array_unique 只能操作平面数组,您不能直接使用它。但是,您可以先将所有的 'md5' 值映射到一个平面数组中,使其唯一,并使用 array_intersect_key 获取元素:
$allMd5s = array_map(function($v) {return $v['md5'];}, $array);

$uniqueMd5s = array_unique($md5);

$result = array_intersect_key($arr, $uniqueMd5s);

1
使用array_filter()。 快速代码测试(不一定反映您的情况,但您应该有个大概的想法):
<?php
header('Content-Type: Text/Plain');
$array = array(
    0 => array('name' => 'samson'),
    1 => array('name' => 'delilah'),
    2 => array('name' => 'samson'),
    3 => array('name' => 'goliath'),
);

$md5Processed = array();

$newArray = array_filter($array, "uniqueMD5");

print_r($newArray);

exit;

function uniqueMD5( $data ){
    global $md5Processed;

    if( !in_array( $data['name'], $md5Processed ) )
    {
        $md5Processed[] = $data['name'];
        return true;
    }
}

1
// your array
$array = array(...);
// will be used to store md5 hashes
$md5 = array();
// walk through array
foreach ($array as $key => $arr) {
  // have we already seen this md5 hash?
  if (in_array($arr['md5'], $md5)){
    // remove element
    unset($array[$key]);
  }else {
    // keep element, but add it's md5
    $md5[] = $arr['md5'];
  }
}

1

简而言之: 必备的一句话:

$out = array_values ( array_intersect_key( $in, array_unique( array_column( $in, 'md5' ) ) ) );

并且逐步(使用我的示例):

$in = [
    [ 'k' => 'a' ],
    [ 'k' => 'a' ],
    [ 'k' => 'b' ]
];

print_r( array_column( $in, 'k' ) );

array_column 返回一个扁平数组,只包含所有 'k' 键的值:

Array
(
    [0] => a
    [1] => a
    [2] => b
)

我们现在可以使用 array_unique 来过滤它:
print_r( array_unique( array_column( $in, 'k' ) ) ) );

获取:

Array
(
    [0] => a
    [2] => b
)

注意我们保留了原始数组的键(0和2)吗? 我们可以使用 array_intersect_key 来实现。它使用键进行比较计算数组的交集。

print_r( array_intersect_key( $in, array_unique( array_column( $in, 'k' ) ) ) );

我们获取原始数组的第一个[0]和第三个[2]条目。
Array
(
    [0] => Array
        (
            [k] => a
        )

    [2] => Array
        (
            [k] => b
        )

)

现在键已经混乱了(如果用于循环可能会导致问题),因此我们将整个内容包装在{{link1:array_values}}中:

print_r(
  array_values( array_intersect_key( $in, array_unique( array_column( $in, 'k' ) ) ) ) 
);

Array
(
    [0] => Array
        (
            [k] => a
        )

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

)

-2

它不会删除md5,因为对于每个数组单元格,它们都是唯一的值。 - MeLight
2
array_unique 无法处理多维数组。该函数使用每个元素的字符串表示来进行比较。 - Felix Kling
不幸的是,array_unique 无法处理多维数组。此外,array_unique 使用 === 运算符来比较两个项目 - 因此您必须小心您的数据存储方式。 - Yzmir Ramirez
@FelixKling:一个数组的字符串表示是什么? - Eric
1
@Eric:据我所知,它是“Array”或类似的东西。也就是说,每个元素(数组)具有相同的字符串表示形式,因此使得这个函数没有用处。 - Felix Kling

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接