php 删除二维数组中的重复值集(无论每行中的顺序或键如何)

polkgigr  于 2023-05-21  发布在  PHP
关注(0)|答案(3)|浏览(124)

我有一个具有以下结构的数组:

[
    ["venue1" => 1, "venue2" => 2],
    ["venue1" => 3, "venue2" => 4],
    ["venue1" => 2, "venue2" => 1],
    ["venue1" => 5, "venue2" => 6],
]

我需要删除重复的“值对”,在本例中是row [0]和row [2]。
我用这段代码试了一下,但它不起作用(当然它也不是很优雅)。

foreach ( $compare_arr as $v1 ) 
{
    $key = array_search( intval($v1[venue1]), array_column( $compare_arr, 'venue2' ) );
    if ( $key <> '' ) unset($compare_arr[$key]);
}
kq0g1dla

kq0g1dla1#

下面是一种由排序值形成中间数组的方法。然后您可以搜索以查找要删除的重复对。

<?php

$venues = 
array (
    0 => 
    array (
      'venue1' => 1,
      'venue2' => 2,
    ),
    1 => 
    array (
      'venue1' => 3,
      'venue2' => 4,
    ),
    2 => 
    array (
      'venue1' => 2,
      'venue2' => 1,
    ),
    3 => 
    array (
      'venue1' => 5,
      'venue2' => 6,
    ),
);

$result = $pairs = $venues;
array_walk($pairs, 'sort');

var_export($pairs);

foreach($pairs as $k => $pair) {
    if(count(array_keys($pairs, $pair)) > 1) {
        unset($result[$k]);
    }
}

var_export($result);

输出:

array (
    0 => 
    array (
      0 => 1,
      1 => 2,
    ),
    1 => 
    array (
      0 => 3,
      1 => 4,
    ),
    2 => 
    array (
      0 => 1,
      1 => 2,
    ),
    3 => 
    array (
      0 => 5,
      1 => 6,
    ),
  )array (
    1 => 
    array (
      'venue1' => 3,
      'venue2' => 4,
    ),
    3 => 
    array (
      'venue1' => 5,
      'venue2' => 6,
    ),
  )

如果你想删除重复的内容而不是完全删除重复的内容,你可以对上面的排序数组执行array_unique,然后使用剩余的键来过滤原始数组。

$tmp     = $venues;
array_walk($tmp, 'sort');
$tmp     = array_unique($tmp, SORT_REGULAR);
$result  = array_intersect_key($venues, $tmp);
var_export($result);

输出:

array (
    0 => 
    array (
      'venue1' => 1,
      'venue2' => 2,
    ),
    1 => 
    array (
      'venue1' => 3,
      'venue2' => 4,
    ),
    3 => 
    array (
      'venue1' => 5,
      'venue2' => 6,
    ),
  )
mlmc2os5

mlmc2os52#

您也可以先循环数组,根据已排序的键创建一个复合键。
然后,您可以过滤结果,只保留计数为2的数组,因为没有重复项,所以不添加任何内容。
举个例子

$result = [];
$compare_arr = [
    ["venue1" => 1, "venue2" => 2],
    ["venue1" => 3, "venue2" => 4],
    ["venue1" => 2, "venue2" => 1],
    ["venue1" => 5, "venue2" => 6],
];

foreach ($compare_arr as $v1) {
    sort($v1);
    $cKey = $v1[0] .'-'. $v1[1];
    if (array_key_exists($cKey, $result)) {
        $result[$cKey][] = $v1;
        continue;
    }
    $result[$cKey] = $v1;
}
$result = array_filter($result, function($item) {
    return count($item) === 2;
});

print_r($result);

输出

Array
(
    [3-4] => Array
        (
            [0] => 3
            [1] => 4
        )

    [5-6] => Array
        (
            [0] => 5
            [1] => 6
        )

)

你可以看到复合键是中间有一个-的值。如果你想让键从0开始编号,你可以使用array_values
Php demo

编辑

如果你想保留第一个匹配的单对,你可以检查复合键,如果它已经存在,继续循环,而不覆盖现有的一个。

$result = [];
$compare_arr = [
    ["venue1" => 1, "venue2" => 2],
    ["venue1" => 3, "venue2" => 4],
    ["venue1" => 2, "venue2" => 1],
    ["venue1" => 5, "venue2" => 6]
];

foreach ($compare_arr as $v1) {
    sort($v1);
    $cKey = $v1[0] .'-'. $v1[1];
    if (array_key_exists($cKey, $result)) {
        continue;
    }
    $result[$cKey] = $v1;
}

print_r($result);

输出

Array
(
    [1-2] => Array
        (
            [0] => 1
            [1] => 2
        )

    [3-4] => Array
        (
            [0] => 3
            [1] => 4
        )

    [5-6] => Array
        (
            [0] => 5
            [1] => 6
        )

)

Php demo

pqwbnv8z

pqwbnv8z3#

无论使用经典的foreach()循环还是函数迭代,都没有理由对输入数组进行多次迭代。
这段代码看起来与ThefourthBird的答案几乎相同,但我不喜欢不必要地使用continue。此代码段将确保结果数组中的行没有100%共享的地点值(以任何顺序)。子阵列键也不会遭受重新排序;换句话说,第一元素key将是venue1,然后第二元素将是venue2。使用implode()提供了额外的灵活性,因为如果每行中的元素数量发生变化,则不需要更改代码。

$result = [];
foreach ($data as $index => $row) {
    sort($row);
    $key = implode('-', $row);
    if (!isset($result[$key])) {
        $result[$key] = $data[$index];
    }
}
var_export(array_values($result));

输出:

array (
  0 => 
  array (
    'venue1' => 1,
    'venue2' => 2,
  ),
  1 => 
  array (
    'venue1' => 3,
    'venue2' => 4,
  ),
  2 => 
  array (
    'venue1' => 5,
    'venue2' => 6,
  ),
)

要完全删除共享地点值的所有行,请维护一个“发现”数组和一个“结果”数组。
代码:(Demo

$result = [];
foreach ($data as $index => $row) {
    sort($row);
    $key = implode('-', $row);
    if (!isset($found[$key])) {
        $found[$key] = true;
        $result[$key] = $data[$index];
    } else {
        unset($result[$key]);
    }
}
var_export(array_values($result));

输出:

array (
  0 => 
  array (
    'venue1' => 3,
    'venue2' => 4,
  ),
  1 => 
  array (
    'venue1' => 5,
    'venue2' => 6,
  ),
)

相关问题