Существует различие в терминах того, каков ведущий фактор.
у Вас есть смутное представление о том, на что класс (или система - это может произойти в различных масштабах, конечно) должен быть похожим, затем продумать тесты, которые дают ему фактическую форму? Это - TDD.
Вы знаете точно, чем общедоступный API класса должен быть, и просто записать тесты перед реализацией? Это - тест первая разработка.
Мой стиль имеет тенденцию быть смесью двух. Иногда очевидно, что API должен прежде писать, что любые тесты - в другой тестируемости случаев действительно управляют дизайном.
Другими словами, TDD запускает с, "Какие вопросы я хочу задать?" тогда как не-TDD (ли тест сначала или не) запускает с, "Какой ответ я хочу дать?"
Хорошо, во-первых, вы, вероятно, хотели иметь $ _ = ~ s /\..*$//
- обратите внимание на отсутствующие s
в вашем примере. Кроме того, вы, вероятно, имеете в виду map
, а не grep
.
Во-вторых, это не то, что вы хотите. Это фактически изменяет @input
! Внутри grep
(и map
и некоторых других мест) $ _
фактически является псевдонимом для каждого значения. Таким образом, вы фактически меняете значение.
Также обратите внимание, что сопоставление с образцом не возвращает совпадающее значение; он возвращает истину (если есть совпадение) или ложь (если нет). Это все единицы, которые вы видите.
Вместо этого сделайте что-то вроде этого:
my @output = map {
(my $foo = $_) =~ s/\..*$//;
$foo;
} @input ;
Сначала копирует $ _
в $ foo
, а затем изменяет $ foo
. Потом, он возвращает измененное значение (хранящееся в $ foo
). Вы не можете использовать return $ foo
, потому что это блок, а не подпрограмма.
Из всех этих ответов никто просто не сказал, что map
возвращает результат последнего вычисленного выражения. Что бы вы ни делали последним, возвращается вещь (или вещи) map
. Это похоже на подпрограмму или do
, возвращающую результат их последнего вычисленного выражения.
Perl v5.14 добавляет неразрушающую замену, о которой я пишу в Используйте флаг подстановки / r, чтобы работа по копии . Вместо того, чтобы возвращать количество замен, он возвращает измененную копию. Используйте флаг / r
:
my @output = map { s/\..*$//r } @input;
Обратите внимание, что вам не нужно использовать $ _
с оператором привязки, поскольку это тема по умолчанию.
Вам не хватает символа s для замены.
$_ =~ /\..*$//
должно быть
$_ =~ s/\..*$//
Также вам может быть лучше использовать s /\.[^\.pting*$ //
в качестве регулярного выражения, чтобы убедиться, что вы просто удалили расширение, даже если имя файла содержит '.' (точка) символ.
derobert показывает вам правильный способ отображения @input
в @output
.
Однако я бы рекомендовал использовать File :: Basename
:
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename;
my @input = qw( a.1.txt b.txt c.txt );
my @output = map { scalar fileparse($_, qr/\.[^.]*/) } @input ;
use Data::Dumper;
print Dumper \@output;
Вывод:
C:\Temp> h $VAR1 = [ 'a.1', 'b', 'c' ];
В вашем примере кода отсутствует s
в операторе сопоставления. В остальном у меня все сработало:
$, = "\n";
my @input = ( "a.txt" , "b.txt" , "c.txt" );
my @output = grep { $_ =~ s/\..*$// } @input;
print @output;
Результат:
a b c
Проблема $ _
псевдонима списка значения уже обсуждались.
Но более того: в заголовке вашего вопроса четко написано «карта», но в вашем коде используется grep, хотя похоже, что он действительно должен использовать карту.
grep
оценит каждый элемент в list, который вы указываете в качестве второго аргумента. И в контексте списка он вернет список, состоящий из тех элементов исходного списка, для которых ваше выражение вернуло истину.
map
, с другой стороны, использует выражение или аргумент блока для преобразования элементов аргумента списка, возвращающего новый список, состоящий из преобразованных аргументов оригинала.
Таким образом, ваша проблема может быть решена с помощью следующего кода:
@output = map { m/(.+)\.[^\.]+/ ? $1 : $_ } @input;
Это будет соответствовать части имени файла, которая не является расширением, и вернет ее в результате оценки или вернет исходное имя, если расширения нет. .
Как уже упоминалось, s /// возвращает количество выполненных замен, а map возвращает последнее выражение, вычисленное из каждая итерация, поэтому ваша карта возвращает все единицы. Один из способов добиться того, что вы хотите:
s/\..*$// for my @output = @input;
Другой способ - использовать фильтр из Algorithm :: Loops