У меня есть массив, который выглядит примерно так:
Array ( [0] => apple ["b"] => banana [3] => cow ["wrench"] => duck )
Я хочу взять этот массив и использовать array_filter или что-то подобное, чтобы удалить элементы с нечисловыми ключами и получить следующий массив:
Array ( [0] => apple [3] => cow )
Я думал об этом, и я не мог придумать, как это сделать, потому что array_filter не предоставляет мою функцию с ключом, и array_walk не может изменять структуру массива (об этом говорится в руководстве по PHP).
Использование цикла foreach
было бы подходящим в этом случае:
foreach ($arr as $key => $value) { if (!is_int($key)) { unset($arr[$key]); } }
сforeach ($arr as $key => $value) { if (!is_int($key)) { unset($arr[$key]); } }
Это можно сделать без написания цикла в одной (длинной) строке :
$a = array_intersect_key($a, array_flip(array_filter(array_keys($a), 'is_numeric')));
Что оно делает:
- Поскольку
array_filter
работает со значениями,array_keys
сначала создает новый массив с ключами как значения (игнорируя исходные значения).- Затем они фильтруются
is_numeric
.- Затем результат возвращается назад, так что клавиши снова становятся ключами.
- Наконец,
array_intersect_key
принимает только элементы из исходного массива, имеющие ключ в результате вышеперечисленного (числовые клавиши).
Однако не спрашивайте меня о производительности.
Начиная с PHP 5.6, теперь можно использовать array_filter
в компактной форме:
array_filter($array, function ($k) { return is_numeric($k); }, ARRAY_FILTER_USE_KEY);
Demo.
Этот подход примерно на 20% медленнее, чем цикл for
на моем ящике (1.61s против 1.31s для 1M итераций).
Вот петля:
foreach($arr as $key => $value) { if($key !== 0 and !intval($key)) { unset($arr[$key]); } }
сforeach($arr as $key => $value) { if($key !== 0 and !intval($key)) { unset($arr[$key]); } }