使用字符串值白名单过滤多维数组(包含不规则深度的元素)

问题描述 投票:0回答:5

我有一个多维数组,正在搜索特定值。 如果找到这些值,我需要将这些元素保留在新数组中。

array_intersect()
在 PHP5.3 上运行良好,现在在 5.4 上它抱怨:

注意:数组到字符串的转换。

我发现

array_intersect()
在PHP5.4上的多维数组有问题。 https://bugs.php.net/bug.php?id=60198

这是我正在搜索的

$options
数组:

Array (
    [index1] => html
    [index2] => html
    [index3] => slide
    [index4] => tab
    [index5] => Array ( [0] => 123 )
)

适用于 PHP5.3.x 的代码:

$lookfor   = array('slide', 'tab');
$found     = array_intersect($options, $lookfor);
print_r($found);

Array
(
    [index3] => slide
    [index4] => tab
)

但是在 5.4.x 中,这会引发上述错误。

在没有循环且不使用错误抑制的情况下执行此操作的另一种方法是什么。

php arrays multidimensional-array filter array-intersect
5个回答
21
投票
$array = [
    'a' => 4,
    's' => 5,
    'd' => 6,
];
$onlyKeys = ['s','d'];

$filteredArray = array_filter($array, function($v) use ($onlyKeys) {
    return in_array($v, $onlyKeys);
}, ARRAY_FILTER_USE_KEY);

prinr_r($filteredArray); //  ['s' => 5, 'd' => 6]

要按值过滤,请从参数列表中删除 ARRAY_FILTER_USE_KEY。


13
投票

array_intersect()
不是递归的。该函数假设数组只有一层深,并期望所有数组元素都是标量。当它找到非标量值(即子数组)时,它会抛出通知。

这在array_intersect()

文档中含糊提及:

注意:两个元素被认为相等当且仅当: (string) $elem1 === (string) $elem2。换句话说:当字符串表示相同时。

我能想到的一个解决方案是使用

array_filter()

$lookfor = array('html', 'slide');
$found   = array_filter($options, function($item) use ($lookfor) {
    return in_array($item, $lookfor);
});

注意: 这仍然执行循环,并不比简单的

foreach
好多少。事实上,如果数组很大,它可能会比
foreach
慢。我不知道为什么你要试图避免循环 - 我个人认为如果你只使用循环会更干净。

演示

我能想到的另一个解决方案是在使用之前删除子数组

array_intersect()

<?php

$options = array(
    'index1' => 'html',
    'index2' => 'html',
    'index3' => 'slide',
    'index4' => 'tab',
    'index5' => array(123),
);

$lookfor = array('html', 'slide');
$scalars = array_filter($options,function ($item) { return !is_array($item); });
$found = array_intersect ($scalars, $lookfor);

print_r($found);

演示


5
投票

你可以使用 array_filter()

$arr = array(
  'index1' => 'html',
  'index2' => 'html',
  'index3' => 'slide',
  'index4' => 'tab',
  'index5' => array(0 => 123),
);

$with = array('html', 'slide');
$res = array_filter($arr, function($val) use ($with) {
    return in_array($val, $with);
});

这将返回索引1、索引2和索引3。

编辑:只需阅读您的评论,您的数组将容纳大量条目。

array_filter
当然会根据条件循环并创建一个新数组。


4
投票

您可以使用

array_intersect_key
。 PHP 手册页上针对此函数的 用户贡献的最佳答案 为您的特定问题提供了解决方案:

$found = \array_intersect_key($options, \array_flip($lookfor));

array_flip
交换键和值。 这是必需的,因为
array_intersect_key
使用所有数组中的键来执行交集。 生成的数组仅包含所有传递的数组中存在的键以及第一个数组中的值。


1
投票

您仍然可以享受数组与本机函数相交及其内置优化,而不是进行(更重的)迭代调用

in_array()
;您只需拨打
array_uintersect()
即可。

代码:(演示

var_export(
    array_uintersect($options, $lookfor, fn($a, $b) => $a <=> $b)
);

输出:

array (
  'index1' => 'html',
  'index2' => 'html',
  'index3' => 'slide',
)
© www.soinside.com 2019 - 2024. All rights reserved.