在 PHP 中检查一个数组的元素是否在另一个数组中

在 PHP 中有两个数组,如下所示:

人物:

Array
(
[0] => 3
[1] => 20
)

通缉犯:

Array
(
[0] => 2
[1] => 4
[2] => 8
[3] => 11
[4] => 12
[5] => 13
[6] => 14
[7] => 15
[8] => 16
[9] => 17
[10] => 18
[11] => 19
[12] => 20
)

如何检查 元素的 任何是否在 通缉犯数组中?

在这个例子中,它应该返回 true,因为 20通缉犯中。

146637 次浏览

你可以使用 array_intersect()

$result = !empty(array_intersect($people, $criminals));

该代码是无效的,因为您只能将变量传递到语言构造中。

你必须用两句话来表达:

$result = array_intersect($people, $criminals);
$result = !empty($result);

使用 array _ intersect ()和 count ()(而不是 null)没有什么错。

例如:

$bFound = (count(array_intersect($criminals, $people))) ? true : false;

如果‘ em pty’不是最好的选择,那么这个怎么样:

if (array_intersect($people, $criminals)) {...} //when found

或者

if (!array_intersect($people, $criminals)) {...} //when not found

也可以按照以下方式使用 in _ array:

<?php
$found = null;
$people = array(3,20,2);
$criminals = array( 2, 4, 8, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
foreach($people as $num) {
if (in_array($num,$criminals)) {
$found[$num] = true;
}
}
var_dump($found);
// array(2) { [20]=> bool(true)   [2]=> bool(true) }

尽管 array _ intersect 使用起来当然更方便,但是它在性能方面并没有真正的优势。我也创作了这个剧本:

<?php
$found = null;
$people = array(3,20,2);
$criminals = array( 2, 4, 8, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
$fastfind = array_intersect($people,$criminals);
var_dump($fastfind);
// array(2) { [1]=> int(20)   [2]=> int(2) }

然后,我分别在: http://3v4l.org/WGhO7/perf#tabshttp://3v4l.org/g1Hnu/perf#tabs运行这两个代码片段,并检查每个代码片段的性能。有趣的是,PHP5.6的总 CPU 时间,即用户时间 + 系统时间是相同的,内存也是相同的。对于 in _ array,PHP5.4下的总 CPU 时间比 array _ intersect 要少,尽管这个比例很小。

In _ array 与 array _ intersect 的性能测试:

$a1 = array(2,4,8,11,12,13,14,15,16,17,18,19,20);


$a2 = array(3,20);


$intersect_times = array();
$in_array_times = array();
for($j = 0; $j < 10; $j++)
{
/***** TEST ONE array_intersect *******/
$t = microtime(true);
for($i = 0; $i < 100000; $i++)
{
$x = array_intersect($a1,$a2);
$x = empty($x);
}
$intersect_times[] = microtime(true) - $t;




/***** TEST TWO in_array *******/
$t2 = microtime(true);
for($i = 0; $i < 100000; $i++)
{
$x = false;
foreach($a2 as $v){
if(in_array($v,$a1))
{
$x = true;
break;
}
}
}
$in_array_times[] = microtime(true) - $t2;
}


echo '<hr><br>'.implode('<br>',$intersect_times).'<br>array_intersect avg: '.(array_sum($intersect_times) / count($intersect_times));
echo '<hr><br>'.implode('<br>',$in_array_times).'<br>in_array avg: '.(array_sum($in_array_times) / count($in_array_times));
exit;

结果如下:

0.26520013809204
0.15600109100342
0.15599989891052
0.15599989891052
0.1560001373291
0.1560001373291
0.15599989891052
0.15599989891052
0.15599989891052
0.1560001373291
array_intersect avg: 0.16692011356354


0.015599966049194
0.031199932098389
0.031200170516968
0.031199932098389
0.031200885772705
0.031199932098389
0.031200170516968
0.031201124191284
0.031199932098389
0.031199932098389
in_array avg: 0.029640197753906

In _ array 至少快5倍。注意,一旦找到结果,我们就“中断”。

这是我研究了一段时间后的一个方法。我想制作一个 LaravelAPI 端点来检查一个字段是否“正在使用”,所以重要的信息是: 1)哪个数据库表?2)什么数据库列?3)该列中是否有与搜索条件相匹配的值?

了解了这一点,我们就可以构建我们的关联数组:

$SEARCHABLE_TABLE_COLUMNS = [
'users' => [ 'email' ],
];

然后,我们可以设置我们要检查的值:

$table = 'users';
$column = 'email';
$value = 'alice@bob.com';

然后,我们可以使用 array_key_exists()in_array()互相执行一个一步、两个步骤的组合,然后根据 truthy条件进行操作:

// step 1: check if 'users' exists as a key in `$SEARCHABLE_TABLE_COLUMNS`
if (array_key_exists($table, $SEARCHABLE_TABLE_COLUMNS)) {


// step 2: check if 'email' is in the array: $SEARCHABLE_TABLE_COLUMNS[$table]
if (in_array($column, $SEARCHABLE_TABLE_COLUMNS[$table])) {


// if table and column are allowed, return Boolean if value already exists
// this will either return the first matching record or null
$exists = DB::table($table)->where($column, '=', $value)->first();


if ($exists) return response()->json([ 'in_use' => true ], 200);
return response()->json([ 'in_use' => false ], 200);
}


// if $column isn't in $SEARCHABLE_TABLE_COLUMNS[$table],
// then we need to tell the user we can't proceed with their request
return response()->json([ 'error' => 'Illegal column name: '.$column ], 400);
}


// if $table isn't a key in $SEARCHABLE_TABLE_COLUMNS,
// then we need to tell the user we can't proceed with their request
return response()->json([ 'error' => 'Illegal table name: '.$table ], 400);

我对特定于 Laravel 的 PHP 代码表示歉意,但是我将不再使用它,因为我认为您可以将它作为伪代码来阅读。重要的部分是同步执行的两个 if语句。

array_key_exists()in_array()是 PHP 函数。

来源:

我在上面展示的算法的优点是,您可以创建一个 REST 端点,比如 GET /in-use/{table}/{column}/{value}(其中 tablecolumnvalue是变量)。

你可以:

$SEARCHABLE_TABLE_COLUMNS = [
'accounts' => [ 'account_name', 'phone', 'business_email' ],
'users' => [ 'email' ],
];

然后你可以发出 GET 请求,比如:

GET /in-use/accounts/account_name/Bob's Drywall(您可能需要对最后一部分进行 uri 编码,但通常不需要)

GET /in-use/accounts/phone/888-555-1337

GET /in-use/users/email/alice@bob.com

还要注意,没有人能够做到:

因为 password没有列在 user允许列的列表中。

祝你一路顺风。

我已经创建了一个干净的 Helper 函数供您使用。

if (!function_exists('array_has_one')) {


/**
* array_has_one
*
* Uses the search array to match at least one of the haystack to return TRUE
*
* @param {array} $search
* @param {array} $haystack
* @return {boolean}
*/
function array_has_one(array $search, array $haystack){
if(!count(array_intersect($search, $haystack)) === FALSE){
return TRUE;
}else{
return FALSE;
}


}
}

你会把这个当做

if(array_has_one([1,2,3,4,5], [5,6,7,8,9])){
echo "FOUND 5";
}