Я пытаюсь создать чистый массив из строки, которую определят мои пользователи.
Строка может содержать недействительные идентификаторы, пробелы и т. д. Я проверяю элементы с помощью объекта значения в функции обратного вызова для array_filter
.
$definedIds = "123,1234,1243, 12434 , asdf"; //from users panel
$validIds = array_map(
'trim',
array_filter(
explode(",", $definedIds),
function ($i) {
try {
new Id(trim($i));
return true;
} catch (\Exception $e) {
return false;
}
}
)
);
Это нормально работает, но я применяю trim
дважды. Есть ли лучший способ сделать эту или другую функцию PHP, в которой я могу изменить элемент, прежде чем сохранять его в возвращаемом массиве?
ПРИМЕЧАНИЕ. Я также мог бы вызвать array_map
в первом параметре array_filter
, но в любом случае я бы дважды перебирал массив.
каков ваш ожидаемый результат?
почему бы вам не использовать str_replace
для удаления пробелов перед отображением массива?
@BeingSunny, это [123,1234,1243,12434]
@mim. это хорошая идея для этого конкретного случая, но все еще интересно, есть ли функция, использующая обратный вызов для заполнения возвращаемого массива
@CarlosAS, тогда вы можете попробовать array_walk_recursive
.
Это зависит от того, заботитесь ли вы о производительности. Если вы это сделаете, не используйте map + filter, а используйте простой цикл for и манипулируйте своим массивом на месте:
$arr = explode(',', $input);
for($i=count($arr)-1; $i>=0; $i--) {
// make this return trimmed string, or false,
// and have it trim the input instead of doing
// that upfront before passing it into the function.
$v = $arr[$i] = Id.makeValid($arr[$i]);
// weed out invalid ids
if ($v === false) {
array_splice($arr, $i, 1);
}
}
// at this point, $arr only contains valid, cleaned ids
Конечно, если это несущественный код, то двойная обрезка В самом деле не повлияет на производительность, но вы все равно можете все исправить:
$arr = explode(',', $input);
$arr = array_filter(
array_map('Id.isValidId', $arr),
function ($i) {
return $i !== false;
}
);
В этом примере мы отображаем первый, используя эту функцию, поэтому мы получаем массив идентификаторов и значений false
, а затем мы фильтруем его, чтобы все, что false
, было выброшено, вместо того, чтобы сначала фильтровать, а затем отображать.
(В обоих случаях код, отвечающий за проверку действительности, находится в классе Id
, и он либо возвращает очищенный идентификатор, либо false
)
На самом деле вы можете сделать это по-другому, но на вашем месте я бы сделал это так. Здесь я просто использовал только один отделка
<?php
$definedIds = "123,1234,1243, 12434 , asdf"; //from users panel
function my_filter($b){
if (is_numeric($b)){
return true;
}
}
print '<pre>';
$trimmed = array_map('trim',explode(',',$definedIds));
print_r(array_filter($trimmed,my_filter));
print '</pre>';
?>
Вывод программы:
Array
(
[0] => 123
[1] => 1234
[2] => 1243
[3] => 12434
)
Это тот же код моего вопроса, вы только что назвали функцию обратного вызова и удалили проверки объекта значения ...
@CarlosAS: P Да, ты ri8, я просто подсознательно опубликовал ту же логику, что и ты. Смотрите мою правку сейчас Я использовал только один раз отделка внутри array_map ()
В качестве небольшого предложения не заставляйте конструктор бросать, а вместо этого используйте статически определенный
Id.isValidId(input)
, который вы можете вызывать, поэтому вам не нужно брать на себя выделение памяти, модификацию таблицы символов и сборку мусора. Вы ничего не делаете с создаваемым объектомId
, поэтому, если вы используете его только для проверки правильности идентификатора, сделайте эту функцию специальной функцией, которую вы можете вызвать.