Почему моя Perl-карта ничего не возвращает?

StackOverflow https://stackoverflow.com/questions/12103

  •  08-06-2019
  •  | 
  •  

Вопрос

Когда я выполняю следующее утверждение:

@filtered = map {s/ //g} @outdata;

он возвращает пустой список вместо отфильтрованного списка, который я ожидал.То, что я пытаюсь сделать, это удалить все вхождения   из массива string (который представляет собой XML-файл).

Очевидно, я чего-то не понимаю.Кто-нибудь может подсказать мне, каким может быть правильный способ сделать это, и почему это не работает у меня как есть?

Это было полезно?

Решение

Попробуй это:

@filtered = map {s/ //g; $_} @outdata;

Проблема в том, что оператор s в perl изменяет $_, но на самом деле возвращает количество внесенных им изменений.Таким образом, дополнительный $_ в конце приводит к тому, что perl возвращает измененную строку для каждого элемента @outdata.

Другие советы

Обратите внимание, что map также изменит ваш исходный массив.Таким образом, вы могли бы либо сделать:

map {s/ //g} @outdata;

и вообще пропустите переменную @filtered, или, если вам нужно сохранить оригиналы,

@filtered = @outdata;
map {s/ //g} @filtered;

Хотя, в этом случае, было бы более удобно использовать foreach:

s/ //g foreach @filtered;

Проблема ответа Грега заключается в том, что он изменит исходный массив, поскольку $_ передаются с псевдонимами.Вам нужно:

@filtered = map { (my $new = $_) =~ s/ //g; $new} @outdata;

Чтобы развить мысль Титония, это тоже поможет:

@filtered = map {local $_=$_; s/ //g; $_} @outdata;

"Локальный" гарантирует, что вы работаете с копией, а не с оригиналом.

В perl 5.14 вы могли бы использовать /r модификатор регулярного выражения для произвести неразрушающую замену.

@filtered = map {s/ //gr} @outdata;
use Algorithm::Loops "Filter";
@filtered = Filter { s/ //g } @outdata;

В качестве контрапункта к ответу Грега вы могли бы злоупотреблять grep:

@filtered = grep {s/ //g; 1} @outdata;

Не делай этого.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top