PHP: как использовать array filter() для фильтрации ключей массива?



функция обратного вызова в array_filter() передает только значения массива, а не ключи.



если у меня есть:



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

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


каков наилучший способ удалить все ключи в $my_array не в $allowed массив?



желаемый результат:



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

13 ответов:

PHP 5.6 ввел третий параметр в array_filter(),flag, что вы можете установить в ARRAY_FILTER_USE_KEY для фильтрации по ключу вместо значения:

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

ясно, что это не так элегантно, как array_intersect_key($my_array, array_flip($allowed)), но он предлагает дополнительную гибкость выполнения произвольного теста против ключа, например $allowed может содержать шаблоны регулярных выражений вместо простых строк.

вы также можете использовать ARRAY_FILTER_USE_BOTH иметь оба значение и ключ, переданные в функцию фильтра. Вот надуманный пример, основанный на первом, но обратите внимание, что я бы не рекомендовал кодировать правила фильтрации с помощью $allowed таким образом:

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

С array_intersect_key и array_flip:

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

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

мне нужно сделать то же самое, но с более сложным array_filter на клавишах.

вот как я это сделал, используя аналогичный метод.

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

выводит результат:

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

вот это более гибкое решение с помощью закрытия:

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

выходы:

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

Так что в функции, вы можете сделать другие конкретные тесты.

если вы ищете метод для фильтрации массива по строке, встречающейся в ключах, вы можете использовать:

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

результат print_r($mResult) и

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

адаптация этого ответа, который поддерживает регулярные выражения

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

выход

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

как получить текущий ключ массива при использовании array_filter

независимо от того, как мне нравится решение Винсента для проблемы Мачека, он на самом деле не использует array_filter. Если вы пришли сюда из поисковой системы вы может быть искали что-то вроде этого ( 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';
}

он передает массив, который вы фильтруете, как ссылку на обратный вызов. Как array_filter обычно не перебирает массив, увеличивая его публичный внутренний указатель вы должны продвигать его самостоятельно.

здесь важно то, что вам нужно убедиться, что Ваш массив сброшен, иначе вы можете начать прямо в середине его.

на PHP > = 5.4 вы можете сделать обратный вызов еще короче:

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

вот менее гибкая альтернатива с помощью unset ():

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

результат print_r($array) время:

Array
(
    [2] => two
)

Это не применимо, если вы хотите сохранить отфильтрованы значения для последующего использования, но аккуратнее, если вы уверены, что это не так.

начиная с PHP 5.6, вы можете использовать ARRAY_FILTER_USE_KEY флаг array_filter:

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


В противном случае, вы можете использовать эту функцию (от 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);
});


А вот дополненная версия моей, которая принимает обратный вызов или непосредственно ключи:

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


И последнее, но не менее важное, вы также можете использовать простой foreach:

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

возможно, перебор, если вам это нужно только один раз, но вы можете использовать YaLinqo библиотека* для фильтрации коллекций (и выполнения любых других преобразований). Эта библиотека позволяет формировать SQL-подобные запросы на объекты с плавным синтаксисом. Его where функция принимает обратный вызов с двумя аргументами: значение и ключ. Например:

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

(The where функция возвращает итератор, так что если вам нужно только перебрать с foreach по результирующей последовательности один раз,->toArray() можно удалить.)

* я

С помощью этой функции можно фильтровать многомерный массив

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];

}

функция фильтра массива из php:

array_filter ( $array, $callback_function, $flag )

$array-это входной массив

$callback_function - функция обратного вызова для использования, если функция обратного вызова возвращает правда, текущее значение из массива возвращается в результирующий массив.

$флаг - это необязательный параметр, он определит, какие аргументы отправляются в функцию обратного вызова. Если этот параметр пуст, то функция будет принимать значения массива аргумент. Если вы хотите отправить ключ массива в качестве аргумента, то используйте $ flag как ARRAY_FILTER_USE_KEY. Если вы хотите отправить оба ключа и значения, вы должны использовать $ flag как ARRAY_FILTER_USE_BOTH .

Например : рассмотрим простой массив

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

если вы хотите фильтровать массив на основе ключ массива, нам нужно использовать ARRAY_FILTER_USE_KEY как третий параметр функции массива array_filter.

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

если вы хотите фильтровать массив на основе ключ массива и значение массива, нам нужно использовать ARRAY_FILTER_USE_BOTH как третий параметр функции array array_filter.

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

пример функции обратного вызова:

 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;
    }
}

он будет выводить

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

/ / отфильтровать элементы массива с ключами короче 4 символов // С помощью анонимной функции с закрытием...

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), сравнение(4));

print_r($output);
enter image description here

$elements_array = ['first', 'second'];

функция для удаления некоторых элементов массива

function remove($arr, $data) {
    return array_filter($arr, function ($element) use ($data) {
        return $element != $data;
    });
}

звонок и печати

print_r(remove($elements_array, 'second'));

результат Array ( [0] => first )

Comments

    Ничего не найдено.