如何使用两个键删除数组中的重复项?

Posted

技术标签:

【中文标题】如何使用两个键删除数组中的重复项?【英文标题】:How to remove duplicates in an array using two keys? 【发布时间】:2012-12-11 04:20:14 【问题描述】:

以下脚本将根据单键从数组中删除重复项。我通过以下参考找到了它。 参考:remove duplicates from array (array unic by key)

我遇到的问题是 $initial_data 数组可能包含具有相同 [Post_Date] 值但不同 [Item_Title] 值的项目.

有没有办法修改代码,使其仅在 [Post_Date][Item_Title] 值相同的情况下删除重复项?

 // Remove Duplicates based on 'Post_Date'
    $_data = array();
    foreach ($initial_data as $v) 
      if (isset($_data[$v['Post_Date']])) 
        continue;
       
      $_data[$v['Post_Date']] = $v;
    
    // if you need a zero-based array, otherwise work with $_data
       $unique_results = array_values($_data);

下面是显示 4 个字段的数组的简化输出。原始数组包含 16 个字段。

$initial_data:原始数据数组。 [Post_Date] 值相同,但 [Item_Title] 值不同。

Array
(
    [0] => Array
        (
            [id] => 22000
            [Category] => vehicles
            [Post_Date] => 1356373690
            [Item_Title] => Car Painting
        )

    [1] => Array
        (
            [id] => 22102
            [Category] => vehicles
            [Post_Date] => 1356373690
            [Item_Title] => Car Repair

        )
...
)

$_data:脚本中的 $_data 数组

Array
(
    [1356373690] => Array
        (
            [id] => 22000
            [Category] => vehicles
            [Post_Date] => 1356373690
            [Item_Title] => Car Painting
        )

    [1356373690] => Array
        (
            [id] => 22102
            [Category] => vehicles
            [Post_Date] => 1356373690
            [Item_Title] => Car Repair

        )
...
)

$unique_results:最终的唯一结果数组。如您所见,脚本仅根据 [Post_Date] 删除了重复的数组项,但我还需要它来评估 [Item_Title] 值是否不同或相同,以便它不会将此数组项视为重复项。

Array
(
    [0] => Array
        (
            [id] => 22000
            [Category] => vehicles
            [Post_Date] => 1356373690
            [Item_Title] => Car Painting
        )
...
)

【问题讨论】:

@Mike Brant 我什么都没试过。上面的代码适用于 1 个键,但我需要为 2 个键修改它。我也尝试了下面的两个建议,但都没有奏效。 【参考方案1】:

你可以用嵌套循环解决这个问题

$uniqueData = array();
foreach ($initialData as $item) 
    $exists = false;

    // check if same item was already added to uniqueData array
    foreach ($uniqueData as $uniqueItem)
        if($item['postDate'] == $uniqueItem['postDate'] && $item['itemTitle'] == $uniqueItem['itemTitle'])
            $exists = true;

    // there is no same item in uniqueData array
    if(!$exists)
        $uniqueData[] = $item;


print_r($uniqueData);

附带说明,在大多数情况下,最好避免使用 continue 语句,因为它会使您的代码更难阅读。

【讨论】:

这至少可以说是低效的。首先,您跳过了使用散列函数快速查找现有项目的可能性。其次,您没有在找到项目时中断循环(因此每次搜索都会一次又一次地遍历整个 $uniqueData 数组)。最后,您在continue 上的声明是……奇怪,至少可以说:默认情况下,此操作没有任何问题或“不可读”,这完全取决于它的使用方式。 @kustrle 试了一下,处理过程大约需要 30 秒,最终得到一个空数组 Array()。我用我的数组 $results 替换了你的变量 $initialData,用我的 Post_Date 替换了你的 postDate,在你的代码中用我的 Item_Title 替换了你的 itemTitle。 我用 4 个项目运行它,它运行良好,没有延迟。 @raina77ow 他没有要求有效的解决方案。过早的优化是万恶之源。如果他没有很多项目,代码将运行得很好。关于继续声明,我可以以您的回答为例。写 if (!isset($_data[$key])) $_data[$key] = $v;看起来比 continue 干净得多。 这是一个演示 sandbox.onlinephpfunctions.com/code/…【参考方案2】:

我想,最简单的方法是使用这两个属性的简单串联作为$data 哈希的键:

$key = $v['Post_Date'] . $v['Item_Title'];
if (isset($_data[$key])) 
  continue;
 
$_data[$key] = $v;

如果 Post_Date 和 Item_Title 可以“重叠”,这显然是行不通的——但从给定的示例中似乎不可能。为了防止这种情况,您可以在 $key 中插入一个分隔符,如下所示:

$key = $v['Post_Date'] . ':' . $v['Item_Title'];

...作为冒号符号显然不会用于存储时间戳字符串。

【讨论】:

以上是关于如何使用两个键删除数组中的重复项?的主要内容,如果未能解决你的问题,请参考以下文章

Vuejs - 如何使用 v-for 获取数组中的所有唯一值(删除重复项)

使用javascript删除与对象的另一个键和值对相对应的对象数组中的重复项

如何从 Javascript 中的数组中删除重复项?

从数组中删除重复的对象

如何比较两个对象数组以删除重复项?

NSSet 在使用 SetWithArray 时如何比较数组中的值以删除重复项