Проверка, есть ли элементы одного массива в другом массиве в PHP - PullRequest
106 голосов
/ 07 февраля 2009

У меня есть два массива в 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
)

Как проверить, есть ли любой элементов People в массиве Wanted Criminals ?

В этом примере он должен вернуть true, поскольку 20 находится в Разыскиваемых преступниках .

Заранее спасибо.

Ответы [ 7 ]

157 голосов
/ 07 февраля 2009

Вы можете использовать array_intersect().

$result = !empty(array_intersect($people, $criminals));
28 голосов
/ 05 января 2012

Нет ничего плохого в использовании array_intersect () и count () (вместо пустых).

Например:

$bFound = (count(array_intersect($criminals, $people))) ? true : false;
23 голосов
/ 13 ноября 2013

, если 'empty' не лучший выбор, как насчет этого:

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

или

if (!array_intersect($people, $criminals)) {...} //when not found
20 голосов
/ 28 июля 2010

Этот код недопустим, поскольку вы можете передавать переменные только в языковые конструкции. empty() является языковой конструкцией.

Вы должны сделать это в две строки:

$result = array_intersect($people, $criminals);
$result = !empty($result);
16 голосов
/ 18 июня 2015

Тест производительности для in_array vs 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 раз быстрее. Обратите внимание, что мы «ломаемся», как только результат найден.

1 голос
/ 03 мая 2019

Вот способ, которым я делаю это после некоторого исследования. Я хотел создать конечную точку API Laravel, которая проверяет, используется ли поле, поэтому важная информация: 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} (где table, column и value - переменные).

Вы можете иметь:

$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

Обратите внимание, что никто не может сделать:

GET /in-use/users/password/dogmeat1337, поскольку password не указан в списке разрешенных столбцов для user.

Удачи в вашем путешествии.

1 голос
/ 05 ноября 2014

Вы также можете использовать 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#tabs и http://3v4l.org/g1Hnu/perf#tabs и проверил производительность каждого из них. Интересно то, что общее время ЦП, то есть время пользователя + системное время одинаково для PHP5.6, и память также одинакова. Общее время ЦП в PHP5.4 для in_array меньше, чем для array_intersect, хотя и незначительно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...