Prüfen, ob sich IRGENDEINES der Elemente eines Arrays in einem anderen Array befindet

Lesezeit: 8 Minuten

Benutzeravatar von Philip Morton
Philipp Morton

Ich habe zwei Arrays in PHP wie folgt:

Menschen:

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

Gesuchte Verbrecher:

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
)

Wie überprüfe ich ob beliebig des Menschen Elemente sind in der Gesuchte Verbrecher Anordnung?

In diesem Beispiel sollte es zurückkehren true da 20 ist in Gesuchte Verbrecher.

Gregs Benutzeravatar
Greg

Sie können verwenden array_intersect().

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

  • Kann empty() nicht mit etwas anderem als einer Variablen verwenden.

    – Grantwparks

    25. September 2009 um 19:21 Uhr

  • Von der Seite, auf die Sie verlinkt haben: „Vor PHP 5.5 unterstützt empty() nur Variablen; alles andere führt zu einem Parsing-Fehler. Mit anderen Worten, Folgendes funktioniert nicht: empty(trim($name)). Stattdessen benutze trim($name) == false.”

    – Grantwparks

    19. September 2013 um 22:31 Uhr

  • Wie in den Kommentaren erwähnt, habe ich das gefunden !empty funktioniert nicht wie erwartet. Stattdessen habe ich verwendet count(): !count(array_intersect($people, $criminals));

    – Mattios550

    30. November 2016 um 21:12 Uhr

  • Warum wird dies als Antwort mit 65 Stimmen markiert, wenn es einen schwerwiegenden Fehler auslöst: Der Rückgabewert der Funktion kann nicht im Schreibkontext verwendet werden?

    – Dave Heq

    27. Januar 2017 um 18:02 Uhr

  • Verwenden !empty() ist unnötig. Wandeln Sie einfach das zurückgegebene Array in einen boolschen Datentyp um. $result = (bool) array_intersect(...); Kein Grund anzurufen empty() oder count(). Ein leeres Array wird false ein nicht leeres Array wird true.

    – mickmackusa

    21. Februar 2022 um 2:16 Uhr

papsys Benutzeravatar
Papy

Es ist wenig falsch, array_intersect() und count() (anstelle von empty) zu verwenden.

Zum Beispiel:

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

  • Daran ist aber nichts auszusetzen count() wird nicht als leistungsfähig angesehen (wenn Sie sich für die Mikrooptimierung interessieren)

    – Jake A. Smith

    14. Mai 2014 um 21:25 Uhr

  • Der ternäre Operator ist in diesem Code redundant, Sie können ihn einfach direkt als bool parsen, indem Sie (bool) vor count aufrufen

    – Ben Gooding

    6. August 2020 um 16:00 Uhr

  • Kann es einfach machen $bFound = count(array_intersect($criminals, $people)) > 0;

    – Lionel Chan

    23. Dezember 2020 um 1:51 Uhr

  • Noch einfacher: $bFound = (bool) array_intersect($criminals, $people); weil leere Arrays falsch sind.

    – mickmackusa

    20. Dezember 2022 um 22:04 Uhr


Wenn “leer” nicht die beste Wahl ist, was ist damit:

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

oder

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

Benutzeravatar von Paul Dragoonis
Paul Dragonis

Dieser Code ist ungültig, da Sie Variablen nur an Sprachkonstrukte übergeben können. empty() ist ein Sprachkonstrukt.

Sie müssen dies in zwei Zeilen tun:

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

Benutzeravatar von Frank Forte
Frank Fort

Leistungstest für 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;

Hier sind die Ergebnisse:

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 ist mindestens 5-mal schneller. Beachten Sie, dass wir “brechen”, sobald ein Ergebnis gefunden wird.

  • Danke für den Maßstab. Wenn Sie also wissen, dass Sie mit kleinen Arrays umgehen, ist es besser, dabei zu bleiben array_intersect().

    – Tokeeen.com

    2. November 2017 um 15:01 Uhr

  • isset ist noch schneller. Und Sie könnten bool val zum Aktivieren oder Deaktivieren verwenden. Auch die Suchwerte als Schlüssel stellen sicher, dass es keine Duplikate gibt. ´array_intersect avg: 0.52077736854553; in_array Durchschnitt: 0,015597295761108; Durchschnittswert: 0,0077081203460693´

    – Baumwolle

    18. Juni 2019 um 12:03 Uhr


  • Es ist noch schneller, wenn Sie in_array mit dem strikten booleschen Satz verwenden. Testen Sie Durchschnitte dreimal schneller als ohne den strengen booleschen Satz.

    – Omarjebari

    24. April 2021 um 10:39 Uhr

  • Es ist unfair, den Benchmark-Vergleich zu machen array_intersect() auch anrufen empty(). empty() ist gar nicht nötig. !array_intersect() ausreicht, um die Arbeit zu erledigen, da nicht überprüft werden muss, ob $x ist deklariert.

    – mickmackusa

    10. Januar um 21:27 Uhr

Sie können in_array auch wie folgt verwenden:

<?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) }

Während array_intersect sicherlich bequemer zu verwenden ist, stellt sich heraus, dass es in Bezug auf die Leistung nicht wirklich überlegen ist. Ich habe auch dieses Skript erstellt:

<?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) }

Dann habe ich beide Snippets ausgeführt unter: http://3v4l.org/WGhO7/perf#tabs und http://3v4l.org/g1Hnu/perf#tabs und überprüfte die Leistung von jedem. Das Interessante ist, dass die gesamte CPU-Zeit, dh Benutzerzeit + Systemzeit, für PHP5.6 gleich ist und der Speicher auch gleich ist. Die Gesamt-CPU-Zeit unter PHP5.4 ist für in_array geringer als für array_intersect, wenn auch geringfügig.

  • Danke für den Maßstab. Wenn Sie also wissen, dass Sie mit kleinen Arrays umgehen, ist es besser, dabei zu bleiben array_intersect().

    – Tokeeen.com

    2. November 2017 um 15:01 Uhr

  • isset ist noch schneller. Und Sie könnten bool val zum Aktivieren oder Deaktivieren verwenden. Auch die Suchwerte als Schlüssel stellen sicher, dass es keine Duplikate gibt. ´array_intersect avg: 0.52077736854553; in_array Durchschnitt: 0,015597295761108; Durchschnittswert: 0,0077081203460693´

    – Baumwolle

    18. Juni 2019 um 12:03 Uhr


  • Es ist noch schneller, wenn Sie in_array mit dem strikten booleschen Satz verwenden. Testen Sie Durchschnitte dreimal schneller als ohne den strengen booleschen Satz.

    – Omarjebari

    24. April 2021 um 10:39 Uhr

  • Es ist unfair, den Benchmark-Vergleich zu machen array_intersect() auch anrufen empty(). empty() ist gar nicht nötig. !array_intersect() ausreicht, um die Arbeit zu erledigen, da nicht überprüft werden muss, ob $x ist deklariert.

    – mickmackusa

    10. Januar um 21:27 Uhr

Benutzeravatar von agm1984
hauptversammlung1984

Hier ist ein Weg, wie ich es mache, nachdem ich es eine Weile recherchiert habe. Ich wollte einen Laravel-API-Endpunkt erstellen, der prüft, ob ein Feld “in Gebrauch” ist, also sind die wichtigen Informationen: 1) welche DB-Tabelle? 2) welche DB-Spalte? und 3) gibt es einen Wert in dieser Spalte, der mit den Suchbegriffen übereinstimmt?

Mit diesem Wissen können wir unser assoziatives Array konstruieren:

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

Dann können wir unsere Werte festlegen, die wir überprüfen werden:

$table="users";
$column = 'email';
$value="[email protected]";

Dann können wir verwenden array_key_exists() und in_array() miteinander, um eine Kombination aus einem und zwei Schritten auszuführen und dann darauf zu reagieren truthy Zustand:

// 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);

Ich entschuldige mich für den Laravel-spezifischen PHP-Code, aber ich werde es belassen, weil ich denke, dass Sie es als Pseudo-Code lesen können. Der wichtige Teil ist die zwei if Anweisungen, die synchron ausgeführt werden.

array_key_exists() und in_array() sind PHP-Funktionen.

Quelle:

Das Schöne an dem Algorithmus, den ich oben gezeigt habe, ist, dass Sie einen REST-Endpunkt wie z GET /in-use/{table}/{column}/{value} (wo table, columnund value sind Variablen).

Du könntest haben:

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

und dann könnten Sie GET-Anfragen stellen wie:

GET /in-use/accounts/account_name/Bob's Drywall (Möglicherweise müssen Sie den letzten Teil uri-codieren, aber normalerweise nicht)

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

GET /in-use/users/email/[email protected]

Beachten Sie auch, dass niemand Folgendes tun kann:

GET /in-use/users/password/dogmeat1337 da password ist nicht in Ihrer Liste der zulässigen Spalten für aufgeführt user.

Viel Glück auf deiner Reise.

  • Ich habe keine Ahnung, was das mit der Frage zu tun hat, aber ich habe einen Blick darauf geworfen und: Ich hoffe wirklich, dass Sie NIEMALS dynamische Daten verwenden $SEARCHABLE_TABLE_COLUMNS! Das schreit nach einer Injektion – egal, ob da ein “ultrasicherer Framework-Query-Builder” dazwischenliegt, der versucht, Tabellen- und Spaltenstrings zu maskieren und zu filtern! Am Ende können Tabellen- und Spaltenstrings nicht per Platzhalter (Prepared Statements) hinzugefügt werden und müssen direkt wie eingefügt werden SELECT ... FROM {$table} WHERE {$column} = :placeholder ..... Ofc hängt von Adaptern ab (mysql, mongo, …) ABER das ist kein Argument zum Sparen! Bitte statisch oder keine Liste =)

    – Baumwolle

    18. Juni 2019 um 11:43 Uhr

1441120cookie-checkPrüfen, ob sich IRGENDEINES der Elemente eines Arrays in einem anderen Array befindet

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy