Vraag PHP: Hoe gebruik je array_filter () om array-sleutels te filteren?


De terugroepfunctie in array_filter() geeft alleen de waarden van de array door, niet de sleutels.

Als ik heb:

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

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

Wat is de beste manier om alle sleutels te verwijderen $my_array die niet in de $allowed serie?

Gewenste output:

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

282
2017-11-23 19:41


oorsprong


antwoorden:


PHP 5.6 heeft een derde parameter geïntroduceerd array_filter(), flag, waar u op kunt instellen ARRAY_FILTER_USE_KEY om te filteren op sleutel in plaats van op waarde:

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

Het is duidelijk dat dit niet zo elegant is als array_intersect_key($my_array, array_flip($allowed)), maar het biedt de extra flexibiliteit van het uitvoeren van een willekeurige test tegen de sleutel, b.v. $allowed kon regex-patronen bevatten in plaats van gewone reeksen.

Je kan ook gebruiken ARRAY_FILTER_USE_BOTH om zowel de waarde als de sleutel door te geven aan uw filterfunctie. Hier is een gekunsteld voorbeeld gebaseerd op het eerste, maar merk op dat ik het gebruik van coderingsfilternormen niet zou aanbevelen $allowed op deze manier:

$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']

197
2017-10-23 08:37



Met array_intersect_key en array_flip:

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

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

402
2017-11-23 19:46



Ik moest hetzelfde doen, maar met een meer complexe array_filter op de toetsen.

Hier is hoe ik het deed, met behulp van een vergelijkbare 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);

Dit levert het resultaat op:

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

39
2017-08-27 03:44



Hier is een meer flexibele oplossing met behulp van een sluiting:

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

uitgangen:

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

Dus in de functie kunt u andere specifieke tests doen.


8
2018-01-25 10:38



Als u op zoek bent naar een methode om een ​​array te filteren op een reeks die voorkomt in sleutels, kunt u het volgende gebruiken:

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

Het resultaat van print_r($mResult) is

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

Een aanpassing van dit antwoord dat reguliere expressies ondersteunt

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

uitgang

Array
(
    [foo] => yes
    [foo2] => yes
    [FooToo] => yes
)

4
2018-02-28 16:42



Hoe de huidige sleutel van een array te krijgen tijdens het gebruik array_filter

Hoe ik de oplossing van Vincent voor het probleem van Maček ook waardeer, het maakt eigenlijk niet uit array_filter. Als je hier uit een zoekmachine kwam, was je misschien op zoek naar zoiets (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';
}

Het geeft de array die u filtert door als een verwijzing naar de callback. Als array_filter niet conventioneel itereren over de array door de openbare interne aanwijzer te vergroten, moet je deze zelf voortzetten.

Wat hier van belang is, is dat u ervoor moet zorgen dat uw array opnieuw wordt ingesteld, anders begint u misschien midden in het array.

In PHP> = 5.4 je zou het terugbellen zelfs nog korter kunnen maken:

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

4
2018-01-23 10:02



Hier is een minder flexibel alternatief voor gebruik unset ():

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

Het resultaat van print_r($array) wezen:

Array
(
    [2] => two
)

Dit is niet van toepassing als u de. Wilt behouden gefilterd waarden voor later gebruik, maar netter, als u zeker weet dat u dat niet doet.


3
2017-10-31 03:50