检查多维数组的任何子数组中的特定键是不是存在特定值
Posted
技术标签:
【中文标题】检查多维数组的任何子数组中的特定键是不是存在特定值【英文标题】:Check if a specific value exists at a specific key in any subarray of a multidimensional array检查多维数组的任何子数组中的特定键是否存在特定值 【发布时间】:2011-10-22 21:09:28 【问题描述】:我需要在多维数组中搜索任何索引子数组中的特定值。
换句话说,我需要检查多维数组的单列是否有值。如果该值存在于多维数组中的任何位置,我想返回true
,否则返回false
$my_array = array(
0 => array(
"name" => "john",
"id" => 4
),
1 => array(
"name" => "mark",
"id" => 152
),
2 => array(
"name" => "Eduard",
"id" => 152
)
);
我想知道检查数组$my_array
是否包含键为“id”的值的最快和最有效的方法。例如,如果id => 152
在多维数组中的任何位置,我想要true
。
【问题讨论】:
【参考方案1】:没有什么比一个简单的循环更快的了。你可以混合和匹配一些数组函数来做到这一点,但它们也只是作为一个循环来实现。
function whatever($array, $key, $val)
foreach ($array as $item)
if (isset($item[$key]) && $item[$key] == $val)
return true;
return false;
【讨论】:
【参考方案2】:** php >= 5.5
你可以用这个
$key = array_search(40489, array_column($userdb, 'uid'));
假设这个多维数组:
$userdb=Array
(
(0) => Array
(
(uid) => '100',
(name) => 'Sandra Shush',
(url) => 'urlof100'
),
(1) => Array
(
(uid) => '5465',
(name) => 'Stefanie Mcmohn',
(pic_square) => 'urlof100'
),
(2) => Array
(
(uid) => '40489',
(name) => 'Michael',
(pic_square) => 'urlof40489'
)
);
$key = array_search(40489, array_column($userdb, 'uid'));
【讨论】:
为什么不简单地$ids = array_column($array, 'id', 'id');
然后isset($ids[40489])
?
嘿,您介意更新您的答案并实施 Elias 的评论吗?
向未来的研究人员澄清$key
可能是0
这是一个虚假值很重要。要知道array_search()
是否找到符合条件的数据,您必须根据需要明确检查$key !== false
或$key === false
。【参考方案3】:
这是 Dan Grossman 的答案的更新版本,它将迎合多维数组(我所追求的):
function find_key_value($array, $key, $val)
foreach ($array as $item)
if (is_array($item) && find_key_value($item, $key, $val)) return true;
if (isset($item[$key]) && $item[$key] == $val) return true;
return false;
【讨论】:
是否可以这样做,但不检查特定值?如果key为空返回true,如果key不为空返回false。 如果没有$key的实际值可以传入怎么办?无论键是什么,我都想搜索整个数组。 听起来你只需要 php 函数 'array_search' 因为输入数据被限制在 2 个级别的深度,所以为这个任务实现递归技术是不必要的开销。如果这是一个递归任务(它不是),那么array_walk_recursive()
将只访问叶节点并消除is_array()
检查。
我的数组的层数比 2 多很多 ?【参考方案4】:
最简单的方法是这样的:
$my_array = array(
0 => array(
"name" => "john",
"id" => 4
),
1 => array(
"name" => "mark",
"id" => 152
),
2 => array(
"name" => "Eduard",
"id" => 152
)
);
if (array_search(152, array_column($my_array, 'id')) !== FALSE)
echo 'FOUND!';
else
echo 'NOT FOUND!';
【讨论】:
【参考方案5】:如果您必须进行大量“id”查找并且它应该非常快,您应该使用包含所有“id”作为键的第二个数组:
$lookup_array=array();
foreach($my_array as $arr)
$lookup_array[$arr['id']]=1;
现在您可以非常快速地检查现有 id,例如:
echo (isset($lookup_array[152]))?'yes':'no';
【讨论】:
【参考方案6】:@Elias Van Ootegan
在以下评论中提供了一个好的解决方案:
$ids = array_column($array, 'id', 'id');
echo isset($ids[40489])?"Exist":"Not Exist";
我试过了,对我有用,谢谢哥们。
已编辑
注意:它将在 PHP 5.5+ 中工作
【讨论】:
请注意array_column
需要 PHP 5.5+ - php.net/manual/en/function.array-column.php【参考方案7】:
正如您的问题,这实际上是一个简单的二维数组不是更好吗?看看-
假设您的二维数组名称 $my_array 和要查找的值是 $id
function idExists($needle='', $haystack=array())
//now go through each internal array
foreach ($haystack as $item)
if ($item['id']===$needle)
return true;
return false;
并称之为:
idExists($id, $my_array);
如您所见,它实际上只检查 key_name 'id' 的任何内部索引是否具有您的 $value。如果 key_name 'name' 也具有 $value
,则此处的其他一些答案也可能为 true【讨论】:
这个将成为页面上表现最好的之一,因为它采用了提前返回,并且在检查针头之前不会创建id
列数据的临时数组。跨度>
【参考方案8】:
TMTOWTDI。以下是按复杂程度排列的几种解决方案。
(以下是关于复杂性的简短入门):O(n)
或“big o”表示 最坏的情况,其中 n
表示数组中的元素数量,o(n)
或“little o" 表示最佳情况。离散数学长话短说,您只需要担心最坏的情况,并确保它不是n ^ 2
或n!
。随着n
的增加,它更多地衡量计算时间的变化,而不是整体计算时间。 Wikipedia has a good article about computational aka time complexity.
如果经验教会了我什么,那就是花太多时间优化程序的 little-o 显然是在浪费时间,最好把时间花在做某事——任何事情——更好。
解决方案 0:O(n) / o(1)
复杂性:
此解决方案具有 1 次比较的最佳情况 - 通过循环进行 1 次迭代,但仅提供匹配值位于数组的位置 0。最坏的情况是它不在数组中,因此必须遍历数组的每个元素。
foreach ($my_array as $sub_array)
if (@$sub_array['id'] === 152)
return true;
return false;
解决方案 1:O(n) / o(n)
复杂性:
无论匹配值在哪里,此解决方案都必须循环遍历整个数组,因此它始终是n
遍历数组。
return 0 < count(
array_filter(
$my_array,
function ($a)
return array_key_exists('id', $a) && $a['id'] == 152;
)
);
解决方案 2:O(n log n) / o(n log n)
复杂性:
哈希插入是log n
的来源; n
哈希插入 = n * log n
。最后有一个哈希查找,它是另一个 log n
,但它不包括在内,因为这正是离散数学的工作原理。
$existence_hash = [];
foreach ($my_array as $sub_array)
$existence_hash[$sub_array['id']] = true;
return @$existence_hash['152'];
【讨论】:
将array_filter()
的返回值转换为(bool)
将使您不必计算结果或与0
进行比较。 3v4l.org/2dVAu 对于任何正在寻找最有效技术(并且 OP 是)的人,使用 array_filter()
将继续迭代输入数组,即使在找到匹配项之后,这也不是最好的方法。
The count()
call is an O(1)
operation,因此没有使用强制转换进行优化。即使你把它写成一个短路的for
循环,最坏的情况仍然是O(n)
,因为$my_array
中不存在ID。
通过转换为(bool)
,array_filter()
的返回值没有函数调用和条件比较,因此转换为布尔类型更加直接和简洁。 DanGrossman 的技术(尽管我会为所有语言结构使用花括号)将是表现最好的,因为它执行有条件的提前返回/中断。我相信你已经知道了;我只是为研究人员说明这个事实。请在您的回答中添加解释,以更好地向新用户发布行为。【参考方案9】:
我看到这篇文章也想做同样的事情,并想出了我自己的解决方案,我想为这个页面的未来访问者提供(并看看这样做是否会出现我没有预见到的任何问题)。
如果你想得到一个简单的true
或false
输出,并且想用一行代码而不用函数或循环来做到这一点,你可以序列化数组,然后使用stripos
搜索值:
stripos(serialize($my_array),$needle)
这似乎对我有用。
【讨论】:
【参考方案10】:你可以只用两个参数来使用它
function whatever($array, $val)
foreach ($array as $item)
if (isset($item) && in_array($val,$item))
return 1;
return 0;
【讨论】:
【参考方案11】:我不知道这对性能来说是好是坏,但这里有一个替代方案:
$keys = array_map(function($element)return $element['id'];, $my_array);
$flipped_keys = array_flip($keys);
if(isset($flipped_keys[40489]))
// true
【讨论】:
你可能也对array_column感兴趣php.net/array_column 我看到了,很多人都建议过,我一个人尝试过,直到我看到上面的 Manuel 才能让它工作。$key = array_search(40489, array_column($userdb, 'uid'));
。我已经找到了我的解决方案,只是想我会分享它。不过,array_search 和 array_column 组合效果很好。
array_column 和 array_flip 工作相同。它只是作为提示仅供参考,array_map 部分可以用它替换,其余部分相同。就我个人而言,我不会将它与 array_search 结合起来,但更像是你对 array_flip 所做的。【参考方案12】:
isset 与 array_key_exits 之间的不同 What's the difference between isset() and array_key_exists()?
== vs === How do the PHP equality (== double equals) and identity (=== triple equals) comparison operators differ?
的区别function specificValue(array $array,$key,$val)
foreach ($array as $item)
if (array_key_exits($item[$key]) && $item[$key] === $val)
return true;
return false;
【讨论】:
【参考方案13】:试试下面的代码。它应该适用于任何类型的多维数组搜索。
这里可以看到LIVE DEMO EXAMPLE
function multi_array_search($search_for, $search_in)
foreach ($search_in as $element)
if ( ($element === $search_for) )
return true;
elseif(is_array($element))
$result = multi_array_search($search_for, $element);
if($result == true)
return true;
return false;
【讨论】:
请注意,使用递归不仅是不必要的开销,还会对第一级元素进行不必要的检查。证明递归对于这个问题是一个不好的选择。 3v4l.org/Aua2W【参考方案14】:function checkMultiArrayValue($array)
global $test;
foreach ($array as $key => $item)
if(!empty($item) && is_array($item))
checkMultiArrayValue($item);
else
if($item)
$test[$key] = $item;
return $test;
$multiArray = array(
0 => array(
"country" => "",
"price" => 4,
"discount-price" => 0,
),);
$test = checkMultiArrayValue($multiArray);
echo "<pre>"
print_r($test);
将返回具有索引和值的数组
【讨论】:
此任务不会受益于递归技术。这个仅代码的答案对于教育/授权成千上万的未来研究人员几乎没有什么作用。当您发布答案时,请务必用简单的英语解释它是如何工作的,以及它与该特定问题的其他答案相比有什么优势。【参考方案15】:我编写了以下函数来确定多维数组是否部分包含某个值。
function findKeyValue ($array, $needle, $value, $found = false)
foreach ($array as $key => $item)
// Navigate through the array completely.
if (is_array($item))
$found = $this->findKeyValue($item, $needle, $value, $found);
// If the item is a node, verify if the value of the node contains
// the given search parameter. E.G.: 'value' <=> 'This contains the value'
if ( ! empty($key) && $key == $needle && strpos($item, $value) !== false)
return true;
return $found;
这样调用函数:
$this->findKeyValue($array, $key, $value);
【讨论】:
没有理由为此任务使用递归。输入数组只有两层深。这是不必要的卷积,不应用于此问题。以上是关于检查多维数组的任何子数组中的特定键是不是存在特定值的主要内容,如果未能解决你的问题,请参考以下文章