455 Stimmen

Array nach seinen Schlüsseln filtern, indem man ein Array von erlaubten Schlüsseln verwendet

Die Rückruffunktion in array_filter() übergibt nur die Werte des Arrays, nicht die Schlüssel.

Wenn ich es habe:

$my_array = array("foo" => 1, "hello" => "world");

$allowed = array("foo", "bar");

Wie lösche ich am besten alle Schlüssel in $my_array die sich nicht in der $allowed Array?

Gewünschter Output:

$my_array = array("foo" => 1);

4voto

flu Punkte 13677

Wie erhält man den aktuellen Schlüssel eines Arrays, wenn man array_filter

Unabhängig davon, wie sehr mir Vincents Lösung für Maceks Problem gefällt, verwendet sie nicht wirklich array_filter . Wenn Sie über eine Suchmaschine hierher gekommen sind und nach einer Möglichkeit suchen, auf den Schlüssel der aktuellen Iteration innerhalb von array_filter Rückruf, haben Sie vielleicht nach etwas wie diesem gesucht ( PHP >= 5.3 ):

$my_array = ["foo" => 1, "hello" => "world"];

$allowed = ["foo", "bar"];

reset($my_array ); // Unnecessary in this case, as we just defined the array, but
                   // make sure your array is reset (see below for further explanation).

$my_array = array_filter($my_array, function($value) use (&$my_array, $allowed) {
  $key = key($my_array); // request key of current internal array pointer
  next($my_array); // advance internal array pointer

  return isset($allowed[$key]);
});

// $my_array now equals ['foo' => 1]

Es übergibt das Array, das Sie filtern, als Referenz an den Callback. Als array_filter nicht auf herkömmliche Weise über das Array iteriert, indem es seinen öffentlichen internen Zeiger erhöht, müssen Sie es selbst vorwärts bewegen.

Wichtig dabei ist, dass Sie sicherstellen müssen, dass Ihr Array zurückgesetzt wird, da Sie sonst möglicherweise mitten im Array beginnen (weil der interne Array-Zeiger von einem Ihrer Codes, der zuvor ausgeführt wurde, dort zurückgelassen wurde).

4voto

Gras Double Punkte 14944

Ab PHP 5.6 können Sie die ARRAY_FILTER_USE_KEY Flagge in array_filter :

$result = array_filter($my_array, function ($k) use ($allowed) {
    return in_array($k, $allowed);
}, ARRAY_FILTER_USE_KEY);

Andernfalls können Sie diese Funktion verwenden ( von TestDummy ):

function filter_array_keys(array $array, $callback)
{
    $matchedKeys = array_filter(array_keys($array), $callback);

    return array_intersect_key($array, array_flip($matchedKeys));
}

$result = filter_array_keys($my_array, function ($k) use ($allowed) {
    return in_array($k, $allowed);
});

Und hier ist eine erweiterte Version von mir, die einen Rückruf oder direkt die Tasten akzeptiert:

function filter_array_keys(array $array, $keys)
{
    if (is_callable($keys)) {
        $keys = array_filter(array_keys($array), $keys);
    }

    return array_intersect_key($array, array_flip($keys));
}

// using a callback, like array_filter:
$result = filter_array_keys($my_array, function ($k) use ($allowed) {
    return in_array($k, $allowed);
});

// or, if you already have the keys:
$result = filter_array_keys($my_array, $allowed));

Zu guter Letzt können Sie auch eine einfache foreach :

$result = [];
foreach ($my_array as $key => $value) {
    if (in_array($key, $allowed)) {
        $result[$key] = $value;
    }
}

4voto

prince jose Punkte 185

Array-Filterfunktion von php:

array_filter ( $array, $callback_function, $flag )

$array - Das ist das Eingabe-Array

$callback_function - Die zu verwendende Callback-Funktion Wenn die Callback-Funktion zurückgibt wahr wird der aktuelle Wert aus array in das Ergebnis-Array zurückgegeben.

$flag - Es ist optionaler Parameter bestimmt, welche Argumente an die Callback-Funktion gesendet werden. Wenn dieser Parameter leer ist, nimmt die Callback-Funktion Array-Werte als Argument. Wenn Sie Array-Schlüssel als Argument senden wollen, dann verwenden Sie $flag als ARRAY_FILTER_VERWENDUNG_SCHLÜSSEL . Wenn Sie sowohl Schlüssel als auch Werte senden wollen, sollten Sie $flag als ARRAY_FILTER_BENUTZEN_BEIDE .

Beispiel: Betrachten Sie ein einfaches Array

$array = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5);

Wenn Sie ein Array basierend auf der Array-Schlüssel , Wir müssen ARRAY_FILTER_VERWENDUNG_SCHLÜSSEL als dritter Parameter der Array-Funktion array_filter.

$get_key_res = array_filter($array,"get_key",ARRAY_FILTER_USE_KEY );

Wenn Sie ein Array basierend auf der Array-Schlüssel und Array-Wert , Wir müssen ARRAY_FILTER_BENUTZEN_BEIDE als dritter Parameter der Array-Funktion array_filter.

$get_both = array_filter($array,"get_both",ARRAY_FILTER_USE_BOTH );

Beispiele für Callback-Funktionen:

 function get_key($key)
 {
    if($key == 'a')
    {
        return true;
    } else {
        return false;
    }
}
function get_both($val,$key)
{
    if($key == 'a' && $val == 1)
    {
        return true;
    }   else {
        return false;
    }
}

Es wird ausgegeben

Output of $get_key is :Array ( [a] => 1 ) 
Output of $get_both is :Array ( [a] => 1 )

4voto

Auf der Grundlage von @sepiariver habe ich einige ähnliche Tests mit PHP 8.0.3 durchgeführt:

$arr = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5, 'f' => 6, 'g' => 7, 'h' => 8];
$filter = ['a', 'e', 'h'];

$filtered = [];
$time = microtime(true);
$i = 1000000;
while($i) {
  $filtered = array_intersect_key($arr, array_flip($filter));
  $i--;
}
print_r($filtered);
echo microtime(true) - $time . " using array_intersect_key\n\n";

$filtered = [];
$time = microtime(true);
$i = 1000000;
while($i) {
  $filtered = array_filter(
    $arr,
    function ($key) use ($filter){return in_array($key, $filter);},
    ARRAY_FILTER_USE_KEY
  );
  $i--;
}
print_r($filtered);
echo microtime(true) - $time . " using array_filter\n\n";

$filtered = [];
$time = microtime(true);
$i = 1000000;
while($i) {
  foreach ($filter as $key)
    if(array_key_exists($key, $arr))
      $filtered[$key] = $arr[$key];
  $i--;
}
print_r($filtered);
echo microtime(true) - $time . " using foreach + array_key_exists\n\n";
  • 0.28603601455688 mit array_intersect_key
  • 1.3096671104431 mit array_filter
  • 0.19402384757996 mittels foreach + array_key_exists

Das "Problem" von array_filter ist, dass es eine Schleife über alle Elemente von $arr macht, während array_intersect_key und foreach nur eine Schleife über $filter machen. Letzteres ist effizienter, vorausgesetzt $filter ist kleiner als $arr.

1voto

Athari Punkte 32497

Vielleicht ein Overkill, wenn Sie es nur einmal brauchen, aber Sie können die YaLinqo Bibliothek*, um Sammlungen zu filtern (und alle anderen Transformationen durchzuführen). Diese Bibliothek ermöglicht die Durchführung von SQL-ähnlichen Abfragen auf Objekte mit einer flüssigen Syntax. Ihre where Funktion akzeptiert einen Rückruf mit zwei Argumenten: einem Wert und einem Schlüssel. Zum Beispiel:

$filtered = from($array)
    ->where(function ($v, $k) use ($allowed) {
        return in_array($k, $allowed);
    })
    ->toArray();

(Die where Funktion gibt einen Iterator zurück. Wenn Sie also nur eine Iteration mit foreach einmal über die resultierende Folge, ->toArray() kann entfernt werden).

* von mir entwickelt

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X