如何使用PHP在多维数组中显示重复数据

时间:2019-02-13 07:15:44

标签: php arrays excel multidimensional-array

我正在使用Spout Excel阅读器从php代码读取Excel文件并将其保存到PHP变量的多维数组中,数组看起来像这样

$array = [
[
    'id[0]' => 'BX-78',
    'Name[0]' => 'XXX',
    'Address[0]' => 'YUUSATD'
],
[
    'id[1]' => 'BX-79',
    'Name[1]' => 'YYY',
    'Address[1]' => 'DHJSHDJGY'
],
[
    'id[2]' => 'BX-80',
    'Name[2]' => 'ZZZ',
    'Address[2]' => 'DDSDSDA'
]
[
    'id[3]' => 'BX-78',
    'Name[3]' => 'AAA',
    'Address[3]' => 'FSDSDS'
][
    'id[4]' => 'BX-81',
    'Name[4]' => 'XXX',
    'Address[4]' => 'DSDSDSD'
]];

现在,如果ID重复显示为重复数据,我想使用两个键['id']['name']从上面的数组中显示重复数据,

  • 如果名称重复,则该行显示为重复数据;如果两者重复,则显示为再次重复行
  • 否则,这是唯一行。

我尝试使用多维数组排序,但是它仅使用一个键来匹配行中的数据。

foreach ($arrExcelData as $v) {
   if (isset($arrExcelData[$v[0]])) {
       // found duplicate
       continue;
    }
    // remember unique item
    $arrExcelData3[$v[0]] = $v;
}

// if you need a zero-based array, otheriwse work with $_data
$arrExcelData2 = array_values($arrExcelData3);

已编辑:预期输出结果:

匹配行:

Id       Name    Address
-------------------------
BX-78    XXX     YUUSATD
BX-78    AAA     DDSDSDA
BX-81    XXX     DSDSDSD`

4 个答案:

答案 0 :(得分:0)

我有一个非常务实的方法:

$spout_output = [
[
    'id[0]' => 'BX-78',
    'Name[0]' => 'XXX',
    'Address[0]' => 'YUUSATD'
],
[
    'id[1]' => 'BX-79',
    'Name[1]' => 'YYY',
    'Address[1]' => 'DHJSHDJGY'
],
[
    'id[2]' => 'BX-80',
    'Name[2]' => 'ZZZ',
    'Address[2]' => 'DDSDSDA'
],
[
    'id[3]' => 'BX-78',
    'Name[3]' => 'AAA',
    'Address[3]' => 'FSDSDS'
],
[
    'id[4]' => 'BX-81',
    'Name[4]' => 'XXX',
    'Address[4]' => 'DSDSDSD'
]];

// store id to row, and name to row mappings.
// id and name will be keys, value will be an array of indexes of the array $spout_output
$id_to_rows = array();
$name_to_rows = array();

$duplicate_ids = array();
$duplicate_names = array();

foreach($spout_output as $row => $data)
{
    $key_id = 'id['.$row.']';
    $key_name = 'Name['.$row.']';

    if(!isset($data[$key_id]))
        continue;

    $value_id = $data[$key_id];
    $value_name = $data[$key_name];

    if(!isset($id_to_rows[$value_id]))
    {
        $id_to_rows[$value_id] = array();
    }
    else
    {
        if(!isset($duplicate_ids[$value_id]))
        {
            $duplicate_ids[$value_id] = $id_to_rows[$value_id];
        }

        $duplicate_ids[$value_id][] = $row;
    }

    if(!isset($name_to_rows[$value_name]))
    {
        $name_to_rows[$value_name] = array();
    }
    else
    {
        if(!isset($duplicate_names[$value_name]))
        {
            $duplicate_names[$value_name] = $name_to_rows[$value_name];
        }

        $duplicate_names[$value_name][] = $row;
    }

    $id_to_rows[$value_id][] = $row;
    $name_to_rows[$value_name][] = $row;
}

echo 'Duplicates:';
echo '<br>';
$shown_rows = array();
foreach($duplicate_ids as $id => $rows)
{
    foreach($rows as $nr)
    {
        echo $id . '|' . $spout_output[$nr]['Name['.$nr.']'] . '|' . $spout_output[$nr]['Address['.$nr.']'];
        echo '<br>';
        $shown_rows[] = $nr;
    }
}

foreach($duplicate_names as $name => $rows)
{
    foreach($rows as $nr)
    {
        // if already shown above, skip this row
        if(in_array($nr, $shown_rows))
            continue;

        echo $spout_output[$nr]['id['.$nr.']'] . '|' . $spout_output[$nr]['Name['.$nr.']'] . '|' . $spout_output[$nr]['Address['.$nr.']'];
        echo '<br>';
        $shown_rows[] = $nr;
    }
}

输出:

Duplicates:
BX-78|XXX|YUUSATD
BX-78|AAA|FSDSDS
BX-81|XXX|DSDSDSD

我认为您的“所需输出”中的地址包含错误? 无论如何,通过上面的代码,我认为您将有足够的映射数据来生成所需的输出。

答案 1 :(得分:0)

您可以执行以下操作:

$dupes = [];
$current = [];

foreach ($array as $index => $entry) {
  $idKey = "id[$index]";
  $nameKey = "Name[$index]";
  if (array_key_exists($entry[$idKey], $current)) {
    $dupes[] = [$entry, $current[$entry[$idKey]]];
  }
  elseif (array_key_exists($entry[$nameKey], $current)) {
    $dupes[] = [$entry, $current[$entry[$nameKey]]];
  }
  else {
    $current[$entry[$idKey]] = $current[$entry[$nameKey]] = $entry;
  }
}

print_r($dupes);

哪个结果包含每个重复项的数组(数组数组)

Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [id[3]] => BX-78
                    [Name[3]] => AAA
                    [Address[3]] => FSDSDS
                )

            [1] => Array
                (
                    [id[0]] => BX-78
                    [Name[0]] => XXX
                    [Address[0]] => YUUSATD
                )

        )

    [1] => Array
        (
            [0] => Array
                (
                    [id[4]] => BX-81
                    [Name[4]] => XXX
                    [Address[4]] => DSDSDSD
                )

            [1] => Array
                (
                    [id[0]] => BX-78
                    [Name[0]] => XXX
                    [Address[0]] => YUUSATD
                )

        )

)

此处演示:https://3v4l.org/JAtNU

答案 2 :(得分:0)

如果要列出重复的值,我认为第二个匹配项的地址应为FSDSDS,因为没有名称为AAA且值为DDSDSDA的项目:

BX-78    AAA     FSDSDS

在这种情况下,您可以做的是首先使用double foreach标记包含重复ID或名称的数组,例如添加一个名为idname的属性,除了当数组本身在第二个循环中时。

此循环后,您可以确定哪些数组是重复的。而不是像id[0]中那样使用对应的索引0,我使用了reset和next,因此它不与这些索引绑定。

要获取过滤后的结果,您可以使用array_reduce检查并取消设置阵列键。

例如:

foreach ($array as $index => $a) {
    foreach ($array as $v) {
        if ($v === $a) continue;
        if (reset($v) === reset($a)) $array[$index]["id"] = "duplicate";
        if (next($v) === next($a)) $array[$index]["name"] = "duplicate";
    }
}

$array = array_reduce($array, function($carry, $item) {
    if (array_key_exists("id", $item) || array_key_exists("name", $item)) {
        unset($item["id"], $item["name"]);
        $carry[] = $item;
    }
    return $carry;
}, []);

print_r($array);

结果

Array
(
    [0] => Array
        (
            [id[0]] => BX-78
            [Name[0]] => XXX
            [Address[0]] => YUUSATD
        )

    [1] => Array
        (
            [id[3]] => BX-78
            [Name[3]] => AAA
            [Address[3]] => FSDSDS
        )

    [2] => Array
        (
            [id[4]] => BX-81
            [Name[4]] => XXX
            [Address[4]] => DSDSDSD
        )

)

查看php demo

答案 3 :(得分:0)

如果您中有人通过键搜索唯一值。

function unique_multidim_array($array, $key) {
                    $temp_array = array();
                    $i = 0;
                    $key_array = array();
                    foreach($array as $val) {
                        if (!in_array($val[$key], $key_array)) {
                            $key_array[$i] = $val[$key];
                            $temp_array[$i] = $val;
                        }
                        $i++;
                    }
                    return $temp_array;
            }
  • 此函数仅获取多维数组和所需字段的键值。

  • 然后一个接一个地(较小的数组)取给定数组的值。

  • 然后遍历给定的数组,并查看带键值对是否与给定键匹配。

  • 之后,如果采用了键值对和给定键函数的匹配,则只需在临时数组(具有唯一值的数组)中插入较小的数组即可。

  • 别忘了增加数组索引($ i)。

  • 然后在函数结束工作后返回具有唯一值的返回数组。