Каково различие между grep и картой в Perl?

Вам нужно связать d для каждой созданной функции. Один из способов сделать это - передать его как параметр со значением по умолчанию:

lambda d=d: self.root.change_directory(d)

Теперь функция внутри функции использует этот параметр, хотя он имеет то же имя, и значение по умолчанию для который вычисляется при создании функции. Чтобы помочь вам увидеть это:

lambda bound_d=d: self.root.change_directory(bound_d)

Помните, как работают значения по умолчанию, например, для изменяемых объектов, таких как списки и dicts, потому что вы привязываете объект.

Эта идиома параметров с значениями по умолчанию достаточно распространены, но может быть неудачным, если вы исследуете параметры функции и определяете, что делать в зависимости от их присутствия. Вы можете избежать параметра с другим закрытием:

(lambda d=d: lambda: self.root.change_directory(d))()
# or
(lambda d: lambda: self.root.change_directory(d))(d)

. Еще лучше, редизайн того, как вы обрабатываете «команды», поможет здесь и должен помочь в другом месте.

14
задан brian d foy 23 February 2009 в 18:09
поделиться

5 ответов

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

$ perl -le 'print join " ", grep $_ & 1, (1, 2, 3, 4, 5)'
1 3 5
$ perl -le 'print join " ", map $_ & 1, (1, 2, 3, 4, 5)'
1 0 1 0 1

Первый пример печатает все нечетные элементы списка, в то время как второй пример печатает 0 или 1 в зависимости от того, нечетен ли соответствующий элемент или нет.

26
ответ дан 1 December 2019 в 06:35
поделиться

Я нахожу, что полезно думать, думают приблизительно grep() и map() в их самой общей форме:

grep {BLOCK} LIST   
map  {BLOCK} LIST

grep() фильтр: это возвращает подмножество объектов из СПИСКА, для которого БЛОК возвращает true.

map() отображающаяся функция: отправьте значение от СПИСКА в БЛОК, и БЛОК возвращает список 0 или больше значений; объединенный набор всех тех вызовов для БЛОКИРОВАНИЯ будет окончательным списком, возвращенным map().

10
ответ дан 1 December 2019 в 06:35
поделиться

map применяет функцию ко всем элементам в списке и возвращает результат.

grep возвраты все элементы в списке, которые оценивают к истинному, когда функция применяется к ним.

my %fruits = (
  banana => {
    color => 'yellow',
    price => 0.79,
    grams => 200
  },
  cherry => {
    color => 'red',
    price => 0.02,
    grams => 10
  },
  orange => {
    color => 'orange',
    price => 1.00,
    grams => 225
  }
);

my %red_fruits = map { $_ => $fruits{$_} }
                   grep { $fruits{$_}->{color} eq 'red' }
                     keys(%fruits);

my @prices = map { $fruits{$_}->{price} } keys(%fruits);
my @colors = map { $fruits{$_}->{color} } keys(%fruits);
my @grams  = map { $fruits{$_}->{grams} } keys(%fruits);

# Print each fruit's name sorted by price lowest to highest:
foreach( sort { $fruits{$a}->{price} <=> $fruits{$b}->{price}} keys(%fruits) )
{
  print "$_ costs $fruits{$_}->{price} each\n";
}# end foreach()
4
ответ дан 1 December 2019 в 06:35
поделиться

Еще одна вещь о grep: в скалярном контексте это говорит Вам, сколько объектов это нашло. Это может быть полезно, если Вы действительно не хотите второй список, но Вы действительно хотите знать сколько объектов определенного вида существует.

my @numbers = qw/1 2 3 4 5 6/;

my @odd_numbers  = grep { $_ & 1 } @numbers; # grep returns (1, 3, 5)

my $how_many_odd = grep { $_ & 1 } @numbers; # grep returns 3

Править: Начиная с OP, который спрашивают в комментарии, я должен сказать, что можно использовать map в скалярном контексте таким же образом. Точка не была этим grep единственный из двух, которые могут сделать это, но что он иногда пригождается, чтобы сделать это с grep.

3
ответ дан 1 December 2019 в 06:35
поделиться

Думайте о grep как о карте с фильтром. карта выполняет итерации и обеспечивает возможность сделать что-то с каждым объектом. Например, эти две строки эквивалентны:

my @copy = @original;
my @copy = map {$_} @original;

Точно так же эти два эквивалентны:

my @copy = grep {-f $_} @original;

@copy = ();
for (@original)
{
  push @copy, $_ if -f $_;
}

grep обеспечивает способность вставить условное выражение и поэтому становится фильтром.

2
ответ дан 1 December 2019 в 06:35
поделиться
Другие вопросы по тегам:

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