wake-up-neo.com

PHP: Wie verwende ich array_filter (), um Array-Schlüssel zu filtern?

Die Callback-Funktion in array_filter() übergibt nur die Werte des Arrays, nicht die Schlüssel.

Wenn ich habe:

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

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

Was ist der beste Weg, um alle Schlüssel in $my_array zu löschen, die sich nicht im $allowed-Array befinden?

Gewünschte Leistung:

$my_array = array("foo" => 1);
312
maček

In PHP 5.6 wurde ein dritter Parameter für array_filter(), flag eingeführt, den Sie auf ARRAY_FILTER_USE_KEY setzen können, um anstelle des Werts nach Schlüssel zu filtern:

$my_array = ['foo' => 1, 'hello' => 'world'];
$allowed  = ['foo', 'bar'];
$filtered = array_filter(
    $my_array,
    function ($key) use ($allowed) {
        return in_array($key, $allowed);
    },
    ARRAY_FILTER_USE_KEY
);

Dies ist offensichtlich nicht so elegant wie array_intersect_key($my_array, array_flip($allowed)) , bietet jedoch die zusätzliche Flexibilität, einen willkürlichen Test gegen den Schlüssel durchzuführen, z. $allowed könnte Regex-Muster anstelle von einfachen Zeichenfolgen enthalten.

Sie können auch ARRAY_FILTER_USE_BOTH verwenden, um sowohl den Wert als auch den Schlüssel an Ihre Filterfunktion zu übergeben. Hier ist ein erfundenes Beispiel, das auf dem ersten basiert, aber ich würde nicht empfehlen, Filterregeln mit $allowed folgendermaßen zu codieren:

$my_array = ['foo' => 1, 'bar' => 'baz', 'hello' => 'wld'];
$allowed  = ['foo' => true, 'bar' => true, 'hello' => 'world'];
$filtered = array_filter(
    $my_array,
    function ($val, $key) use ($allowed) { // N.b. $val, $key not $key, $val
        return isset($allowed[$key]) && (
            $allowed[$key] === true || $allowed[$key] === $val
        );
    },
    ARRAY_FILTER_USE_BOTH
); // ['foo' => 1, 'bar' => 'baz']
233
Richard Turner

Mit array_intersect_key und array_flip :

var_dump(array_intersect_key($my_array, array_flip($allowed)));

array(1) {
  ["foo"]=>
  int(1)
}
425
Vincent Savard

Ich musste dasselbe tun, aber mit einem komplexeren array_filter auf den Tasten. 

So habe ich es gemacht, mit einer ähnlichen Methode.

// Filter out array elements with keys shorter than 4 characters
$a = array(
  0      => "val 0", 
  "one"  => "val one", 
  "two"  => "val two", 
  "three"=> "val three", 
  "four" => "val four", 
  "five" => "val five", 
  "6"    => "val 6"
); 

$f = array_filter(array_keys($a), function ($k){ return strlen($k)>=4; }); 
$b = array_intersect_key($a, array_flip($f));
print_r($b);

Dies gibt das Ergebnis aus:

Array
(
    [three] => val three
    [four] => val four
    [five] => val five
)
39
Christopher

Hier ist eine flexiblere Lösung mit einem Verschluss:

$my_array = array("foo" => 1, "hello" => "world");
$allowed = array("foo", "bar");
$result = array_flip(array_filter(array_flip($my_array), function ($key) use ($allowed)
{
    return in_array($key, $allowed);
}));
var_dump($result);

Ausgänge:

array(1) {
  'foo' =>
  int(1)
}

In der Funktion können Sie also andere spezifische Tests durchführen.

8
COil

So erhalten Sie den aktuellen Schlüssel eines Arrays bei Verwendung von array_filter

Unabhängig davon, wie ich Vincent's Lösung für Mačeks Problem mag, wird array_filter nicht verwendet. Wenn Sie von einer Suchmaschine hierher gekommen sind, suchen Sie vielleicht nach etwas wie diesem ( PHP> = 5.3 ):

$array = ['Apple' => 'red', 'pear' => 'green'];
reset($array); // Unimportant here, but make sure your array is reset

$apples = array_filter($array, function($color) use ($&array) {
  $key = key($array);
  next($array); // advance array pointer

  return key($array) === 'Apple';
}

Es übergibt das von Ihnen gefilterte Array als Referenz für den Rückruf. Da array_filter das Array nicht konventionell durchläuft, indem der öffentliche interne Zeiger erhöht wird, müssen Sie es selbst weiterentwickeln.

Wichtig ist hier, dass Sie sicherstellen müssen, dass Ihr Array zurückgesetzt wird. Andernfalls beginnen Sie vielleicht mitten in dem Array.

In PHP> = 5.4 könnten Sie den Callback noch kürzer machen:

$apples = array_filter($array, function($color) use ($&array) {
  return each($array)['key'] === 'Apple';
}
4
flu

Wenn Sie nach einer Methode suchen, um ein Array nach einer in Schlüsseln vorkommenden Zeichenfolge zu filtern, können Sie Folgendes verwenden:

$mArray=array('foo'=>'bar','foo2'=>'bar2','fooToo'=>'bar3','baz'=>'nope');
$mSearch='foo';
$allowed=array_filter(
    array_keys($mArray),
    function($key) use ($mSearch){
        return stristr($key,$mSearch);
    });
$mResult=array_intersect_key($mArray,array_flip($allowed));

Das Ergebnis von print_r($mResult) ist 

Array ( [foo] => bar [foo2] => bar2 [fooToo] => bar3 )

Eine Anpassung dieser Antwort, die reguläre Ausdrücke unterstützt

function array_preg_filter_keys($arr, $regexp) {
  $keys = array_keys($arr);
  $match = array_filter($keys, function($k) use($regexp) {
    return preg_match($regexp, $k) === 1;
  });
  return array_intersect_key($arr, array_flip($match));
}

$mArray = array('foo'=>'yes', 'foo2'=>'yes', 'FooToo'=>'yes', 'baz'=>'nope');

print_r(array_preg_filter_keys($mArray, "/^foo/i"));

Ausgabe

Array
(
    [foo] => yes
    [foo2] => yes
    [FooToo] => yes
)
4
Nicolas Zimmer

Hier ist eine weniger flexible Alternative mit unset () :

$array = array(
    1 => 'one',
    2 => 'two',
    3 => 'three'
);
$disallowed = array(1,3);
foreach($disallowed as $key){
    unset($array[$key]);
}

Das Ergebnis von print_r($array) ist:

Array
(
    [2] => two
)

Dies gilt nicht, wenn Sie die gefilterten - Werte für eine spätere Verwendung behalten möchten, aber sauberer sind, wenn Sie sicher sind, dass dies nicht der Fall ist.

3
Alastair

Ab PHP 5.6 können Sie das Flag ARRAY_FILTER_USE_KEY in array_filter verwenden:

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


Ansonsten können Sie diese Funktion verwenden ( from 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 Schlüssel 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 verwenden:

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

Vielleicht ein Overkill, wenn Sie es nur einmal brauchen, aber Sie können YaLinqo library * verwenden, um Sammlungen zu filtern (und andere Transformationen durchzuführen). Diese Bibliothek ermöglicht die Ausführung von SQL-ähnlichen Abfragen für Objekte mit fließender Syntax. Seine 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 Funktion where gibt einen Iterator zurück. Wenn Sie also nur einmal mit foreach die resultierende Sequenz einmal durchlaufen müssen, kann ->toArray() entfernt werden.)

* von mir entwickelt

1
Athari

array-Filterfunktion von PHP:

array_filter ( $array, $callback_function, $flag )

$ array - Dies ist das Eingangsarray

$ callback_function - Die zu verwendende Rückruffunktion , Wenn die Rückruffunktion true zurückgibt, wird der aktuelle Wert aus dem Array in das Ergebnisarray zurückgegeben.

$ flag - Es ist optionaler Parameter, es bestimmt, welche Argumente an die Rückruffunktion gesendet werden. Wenn dieser Parameter leer ist, verwendet die Callback-Funktion Array-Werte als Argument. Wenn Sie den Array-Schlüssel als Argument senden möchten, verwenden Sie $ flag als ARRAY_FILTER_USE_KEY. Wenn Sie sowohl Schlüssel als auch Werte senden möchten, sollten Sie $ flag als ARRAY_FILTER_USE_BOTH verwenden.

Zum Beispiel: Betrachten Sie ein einfaches Array

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

Wenn Sie ein Array basierend auf dem Array-Schlüsselfiltern möchten, müssen Sie ARRAY_FILTER_USE_KEY als dritten Parameter der Array-Funktion array_filter verwenden.

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

Wenn Sie ein Array basierend auf dem Arrayschlüssel- und Arraywertfiltern möchten, müssen Sie ARRAY_FILTER_USE_BOTH als dritten Parameter der Arrayfunktion array_filter verwenden.

$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 ) 
0
prince jose

Mit dieser Funktion können Sie ein mehrdimensionales Array filtern

function filter_array_keys($array,$filter_keys=array()){

    $l=array(&$array);
    $c=1;
    //This first loop will loop until the count var is stable//
    for($r=0;$r<$c;$r++){
        //This loop will loop thru the child element list//
        $keys = array_keys($l[$r]);

        for($z=0;$z<count($l[$r]);$z++){
            $object = &$l[$r][$keys[$z]];

            if(is_array($object)){
                $i=0;
                $keys_on_array=array_keys($object);
                $object=array_filter($object,function($el) use(&$i,$keys_on_array,$filter_keys){
                    $key = $keys_on_array[$i];
                    $i++;

                    if(in_array($key,$filter_keys) || is_int($key))return false;                
                    return true;                        
                });
            }

            if(is_array($l[$r][$keys[$z]])){
                $l[] = &$l[$r][$keys[$z]];
                $c++;
            }//IF           
        }//FOR
    }//FOR  

    return $l[0];

}
0
user1220713

// Ausfiltern von Array-Elementen mit Schlüsseln, die kürzer als 4 Zeichen sind. 

function comparison($min)
{
   return function($item) use ($min) { 
      return strlen($item) >= $min;   
   }; 
}

$input = array(
  0      => "val 0",
  "one"  => "val one",
  "two"  => "val two",
  "three"=> "val three",
  "four" => "val four",  
  "five" => "val five",    
  "6"    => "val 6"    
);

$ output = array_filter (array_keys ($ input), Vergleich (4)); 

print_r ($ output);
 enter image description here

0
ZOB