Почему является список моими возвратами карты Perl просто 1's?

Существует различие в терминах того, каков ведущий фактор.

у Вас есть смутное представление о том, на что класс (или система - это может произойти в различных масштабах, конечно) должен быть похожим, затем продумать тесты, которые дают ему фактическую форму? Это - TDD.

Вы знаете точно, чем общедоступный API класса должен быть, и просто записать тесты перед реализацией? Это - тест первая разработка.

Мой стиль имеет тенденцию быть смесью двух. Иногда очевидно, что API должен прежде писать, что любые тесты - в другой тестируемости случаев действительно управляют дизайном.

Другими словами, TDD запускает с, "Какие вопросы я хочу задать?" тогда как не-TDD (ли тест сначала или не) запускает с, "Какой ответ я хочу дать?"

7
задан brian d foy 22 September 2009 в 17:16
поделиться

7 ответов

Хорошо, во-первых, вы, вероятно, хотели иметь $ _ = ~ s /\..*$// - обратите внимание на отсутствующие s в вашем примере. Кроме того, вы, вероятно, имеете в виду map , а не grep .

Во-вторых, это не то, что вы хотите. Это фактически изменяет @input ! Внутри grep map и некоторых других мест) $ _ фактически является псевдонимом для каждого значения. Таким образом, вы фактически меняете значение.

Также обратите внимание, что сопоставление с образцом не возвращает совпадающее значение; он возвращает истину (если есть совпадение) или ложь (если нет). Это все единицы, которые вы видите.

Вместо этого сделайте что-то вроде этого:

my @output = map {
    (my $foo = $_) =~ s/\..*$//;
    $foo;
} @input ;

Сначала копирует $ _ в $ foo , а затем изменяет $ foo . Потом, он возвращает измененное значение (хранящееся в $ foo ). Вы не можете использовать return $ foo , потому что это блок, а не подпрограмма.

16
ответ дан 6 December 2019 в 04:54
поделиться

Из всех этих ответов никто просто не сказал, что map возвращает результат последнего вычисленного выражения. Что бы вы ни делали последним, возвращается вещь (или вещи) map . Это похоже на подпрограмму или do , возвращающую результат их последнего вычисленного выражения.

Perl v5.14 добавляет неразрушающую замену, о которой я пишу в Используйте флаг подстановки / r, чтобы работа по копии . Вместо того, чтобы возвращать количество замен, он возвращает измененную копию. Используйте флаг / r :

my @output = map { s/\..*$//r } @input;

Обратите внимание, что вам не нужно использовать $ _ с оператором привязки, поскольку это тема по умолчанию.

19
ответ дан 6 December 2019 в 04:54
поделиться

Вам не хватает символа s для замены.

$_ =~ /\..*$//

должно быть

$_ =~ s/\..*$//

Также вам может быть лучше использовать s /\.[^\.pting*$ // в качестве регулярного выражения, чтобы убедиться, что вы просто удалили расширение, даже если имя файла содержит '.' (точка) символ.

2
ответ дан 6 December 2019 в 04:54
поделиться

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'
        ];
1
ответ дан 6 December 2019 в 04:54
поделиться

В вашем примере кода отсутствует s в операторе сопоставления. В остальном у меня все сработало:

$, = "\n";
my @input = ( "a.txt" , "b.txt" , "c.txt" );
my @output = grep { $_ =~ s/\..*$// } @input;
print @output;

Результат:

a
b
c
0
ответ дан 6 December 2019 в 04:54
поделиться

Проблема $ _ псевдонима списка значения уже обсуждались.

Но более того: в заголовке вашего вопроса четко написано «карта», но в вашем коде используется grep, хотя похоже, что он действительно должен использовать карту.

grep оценит каждый элемент в list, который вы указываете в качестве второго аргумента. И в контексте списка он вернет список, состоящий из тех элементов исходного списка, для которых ваше выражение вернуло истину.

map , с другой стороны, использует выражение или аргумент блока для преобразования элементов аргумента списка, возвращающего новый список, состоящий из преобразованных аргументов оригинала.

Таким образом, ваша проблема может быть решена с помощью следующего кода:

@output = map { m/(.+)\.[^\.]+/ ? $1 : $_ } @input;

Это будет соответствовать части имени файла, которая не является расширением, и вернет ее в результате оценки или вернет исходное имя, если расширения нет. .

7
ответ дан 6 December 2019 в 04:54
поделиться

Как уже упоминалось, s /// возвращает количество выполненных замен, а map возвращает последнее выражение, вычисленное из каждая итерация, поэтому ваша карта возвращает все единицы. Один из способов добиться того, что вы хотите:

s/\..*$// for my @output = @input;

Другой способ - использовать фильтр из Algorithm :: Loops

1
ответ дан 6 December 2019 в 04:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: