从多维数组中删除所有重复的数据

时间:2019-01-16 03:59:29

标签: php multidimensional-array duplicates filtering

我正在尝试删除所有带有重复数字的键,我尝试了一些此处发布的解决方案,例如我在脚本中使用的解决方案,但是这些解决方案都不适合我的目的。

这是我的数组:

至少重复了4个卡ID。

Array
(
    [0] => Array
        (
            [id_card] => 11883834
            [type] => 1
            [registed] => 1547610891
        )

    [1] => Array
        (
            [id_card] => 20311077
            [type] => 1
            [registed] => 1547610891
        )

    [2] => Array
        (
            [id_card] => 16187903
            [type] => 3
            [registed] => 1547610891
        )

    [3] => Array
        (
            [id_card] => 16354099
            [type] => 1
            [registed] => 1547610891
        )

    [4] => Array
        (
            [id_card] => 21133393
            [type] => 4
            [registed] => 1547610891
        )

    [5] => Array
        (
            [id_card] => 15452852
            [type] => 2
            [registed] => 1547610891
        )

    [6] => Array
        (
            [id_card] => 19775869
            [type] => 2
            [registed] => 1547610891
        )

    [7] => Array
        (
            [id_card] => 20311077
            [type] => 1
            [registed] => 1547610891
        )

    [8] => Array
        (
            [id_card] => 21133393
            [type] => 4
            [registed] => 1547610891
        )

    [9] => Array
        (
            [id_card] => 11883834
            [type] => 1
            [registed] => 1547610891
        )

)
1

此刻我有这样的东西:

<?php
$array_data = array_map('unserialize', array_unique(array_map('serialize', $myArray)));
echo '<pre>';
print_r($array_data);
echo '</pre>';
?>

只有10个键可以正常工作,但是例如50、100个键就无法使用。

任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:3)

所以这里的问题是array_unique解决方案期望整个值是相等的-他们不只是根据您的ID字段进行比较。

相反,您可能希望遍历数组并跟踪您看到的ID,并仅获取那些以前从未看到过的ID的元素。

function filter_duplicate_id_cards($data) {
  $seen = array(); // To keep track of the IDs we've seen
  $filtered = array(); // Will hold the result

  foreach($data as $item) {
    if(array_key_exists($item['id_card'], $seen)) {
      // We already encountered this id card before.
      continue;
    }

    // Never-before seen id card, append it to the result and set the key in $seen
    $filtered[] = $item;
    $seen[$item['id_card']] = TRUE;
  }

  return $filtered;
}

请注意,这使用的是PHP数组的映射形式,而不是仅将可见的ID附加到列表形式,并使用in_array之类的东西来检查是否已看到密钥。出于性能原因,这一点很重要,尤其是如果我们要处理大型数据集时-in_array是O(n),数组中的项目数是array_key_exists是O(1)。< / p>

此函数的通用版本如下所示:

function filter_duplicate_field($data, $field) {
  $seen = array(); // To keep track of the keys we've seen
  $filtered = array(); // Will hold the result

  foreach($data as $item) {
    if(array_key_exists($item[$field], $seen)) {
      // We already encountered this key before.
      continue;
    }

    // Never-before seen key, append it to the result and set the key in $seen
    $filtered[] = $item;
    $seen[$item[$field]] = TRUE;
  }

  return $filtered;
}

然后可以像$result = filter_duplicate_field($data, 'id_card');这样称呼它。

答案 1 :(得分:2)

这不会保留原始的输入顺序,但是由于数据已建立索引,因此我认为这没关系。

在一个内胆中只有3个调用,您可以从后到前分配临时关联密钥,以消除后面的重复(因为php不允许重复密钥),然后可以选择使用array_values()删除临时密钥。没有迭代的函数调用。没有查找数组。

代码:(Demo

$array = [
    ['id_card' => 11883834, 'type' => 1, 'registed' => 1547610891],
    ['id_card' => 20311077, 'type' => 1, 'registed' => 1547610891],
    ['id_card' => 16187903, 'type' => 3, 'registed' => 1547610891],
    ['id_card' => 16354099, 'type' => 1, 'registed' => 1547610891],
    ['id_card' => 21133393, 'type' => 4, 'registed' => 1547610891],
    ['id_card' => 15452852, 'type' => 2, 'registed' => 1547610891],
    ['id_card' => 19775869, 'type' => 2, 'registed' => 1547610891],
    ['id_card' => 20311077, 'type' => 1, 'registed' => 1547610891],
    ['id_card' => 21133393, 'type' => 4, 'registed' => 1547610891],
    ['id_card' => 11883834, 'type' => 1, 'registed' => 1547610891]
];

var_export(array_values(array_column(array_reverse($array), null, 'id_card')));

如果您改变主意要保留第一次出现,可以删除array_reverse()。如果输出中的第一级键不相关,则可以删除array_values()。这些更改将使解决方案成为一个函数调用任务。

p.s。 “已注册 er