Когда я запускаю следующее заявление:
@filtered = map {s/ //g} @outdata;
он возвращает пустой список вместо отфильтрованного списка, который я ожидал. То, что я пытаюсь сделать, это удалить все вхождения
из массива строк (который является файлом XML).
Очевидно, я чего-то не понимаю. Может кто-нибудь сказать мне правильный способ сделать это, и почему это не работает для меня, как есть?
Попробуй это:
@filtered = map {s/ //g; $_} @outdata;
Проблема в том, что оператор s в perl модифицирует $ _, но на самом деле возвращает количество изменений, которые он сделал. Таким образом, дополнительный $ _ в конце заставляет perl возвращать измененную строку для каждого элемента @outdata.
@filtered = map { s/ //gr } @outdata
не затрагивая @outdata
. В качестве контрапункта к ответу Грега, вы можете неправильно использовать grep:
@filtered = grep {s/ //g; 1} @outdata;
Не делай этого.
Обратите внимание, что карта также изменит ваш исходный массив. Так что вы можете сделать:
map {s/ //g} @outdata;
и пропустите переменную @filtered вообще, или если вам нужно сохранить оригиналы,
@filtered = @outdata;
map {s/ //g} @filtered;
Хотя в этом случае может быть более удобочитаемым использовать foreach:
s/ //g foreach @filtered;
map
в пустом контексте обычно считается плохой формой и не говорит ничего сверх for @filtered { ... }
. Чтобы прокомментировать точку зрения Титония, это также поможет:
@filtered = map {local $_=$_; s/ //g; $_} @outdata;
«Местный» гарантирует, что вы работаете с копией, а не с оригиналом.
Ответ Грега состоит в том, что он изменит исходный массив, так как $ _ передаются с псевдонимом. Тебе нужно:
@filtered = map { (my $new = $_) =~ s/ //g; $new} @outdata;
use Algorithm::Loops "Filter";
@filtered = Filter { s/ //g } @outdata;
В Perl 5.14 вы можете использовать модификатор / r regex для неразрушающего замещения .
@filtered = map {s/ //gr} @outdata;