J'ai deux tableaux dans PHP comme suit:
Personnes:
Array
(
[0] => 3
[1] => 20
)
criminels recherchés:
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
)
Comment puis-je vérifier si tous des éléments Personnes sont dans les criminels recherchés tableau?
Dans cet exemple, il devrait retourner true
car 20
est dans criminels recherchés .
Merci d'avance.
Vous pouvez utiliser array_intersect()
.
$result = !empty(array_intersect($people, $criminals));
Il y a peu d'inconvénients à utiliser array_intersect () et count () (au lieu de empty).
Par exemple:
$bFound = (count(array_intersect($criminals, $people))) ? true : false;
si 'vide' n'est pas le meilleur choix, qu'en est-il de ceci:
if (array_intersect($people, $criminals)) {...} //when found
ou
if (!array_intersect($people, $criminals)) {...} //when not found
Ce code n'est pas valide car vous ne pouvez transmettre que des variables dans des constructions de langage. empty()
est une construction de langage.
Vous devez le faire en deux lignes:
$result = array_intersect($people, $criminals);
$result = !empty($result);
Test de performance pour 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;
Voici les résultats:
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 est au moins 5 fois plus rapide. Notez que nous "cassons" dès qu'un résultat est trouvé.
Voici une façon dont je le fais après avoir recherché pendant un moment. Je voulais créer un endpoint d'API Laravel) qui vérifie si un champ est "en cours d'utilisation". Par conséquent, les informations importantes sont les suivantes: 1) quelle table de base de données? 2) quelle colonne de base de données? et 3) y a-t-il une valeur dans cette colonne qui correspond aux termes de la recherche?
Sachant cela, nous pouvons construire notre tableau associatif:
$SEARCHABLE_TABLE_COLUMNS = [
'users' => [ 'email' ],
];
Ensuite, nous pouvons définir nos valeurs que nous vérifierons:
$table = 'users';
$column = 'email';
$value = '[email protected]';
Ensuite, nous pouvons utiliser array_key_exists()
et in_array()
pour exécuter un combo à un, deux étapes, puis agir sur la condition 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);
Je m'excuse pour le code spécifique à Laravel PHP, mais je vais le laisser car je pense que vous pouvez le lire sous forme de pseudo-code. La partie importante sont les deux instructions if
exécutées de manière synchrone.
array_key_exists()
etin_array()
sont PHP fonctions.
la source:
La bonne chose à propos de l’algorithme que j’ai montré ci-dessus est que vous pouvez créer un noeud final REST tel que GET /in-use/{table}/{column}/{value}
) (Où table
, column
et value
sont des variables).
Tu aurais pu:
$SEARCHABLE_TABLE_COLUMNS = [
'accounts' => [ 'account_name', 'phone', 'business_email' ],
'users' => [ 'email' ],
];
et ensuite vous pouvez faire des requêtes GET telles que:
GET /in-use/accounts/account_name/Bob's Drywall
(Vous aurez peut-être besoin d'encoder la dernière partie, mais généralement pas)
GET /in-use/accounts/phone/888-555-1337
GET /in-use/users/email/[email protected]
Notez également que personne ne peut faire:
GET /in-use/users/password/dogmeat1337
Car password
ne figure pas dans votre liste de colonnes autorisées pour user
.
Bonne chance pour ton voyage.
Vous pouvez également utiliser in_array comme suit:
<?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) }
Bien que array_intersect soit certainement plus pratique à utiliser, il n’est pas vraiment supérieur en termes de performances. J'ai aussi créé ce script:
<?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) }
Ensuite, j'ai exécuté les deux extraits respectivement à: http://3v4l.org/WGhO7/perf#tabs et http://3v4l.org/g1Hnu/perf#tabs et vérifié les performances de chacun. Ce qui est intéressant, c’est que le temps CPU total, c’est-à-dire le temps utilisateur et le temps système, est identique pour PHP 5.5 et que la mémoire est identique. Le temps de calcul total sous PHP 5.4 est moins pour in_array que pour array_intersect, même si ce n'est que marginalement.