Как я могу отсортировать один ключ по возрастанию, другой по убыванию, не используя $ b (сравнение) $ a в Perl? - PullRequest
2 голосов
/ 22 февраля 2012

В Perl я могу сделать:

my @unit_indices = sort { 
    $units{$b}[0] <=> $units{$a}[0] 
        or
    $a cmp $b
} keys %units;

, который сортирует по одному полю (элемент массива) по убыванию, а другое (по хеш-ключу) по возрастанию, но вызывает perlcritic, чтобы жаловаться:

Запретить $ b перед $ a в блоках сортировки в строке X, столбец Y. См. Стр. 152 PBP. (Серьезность: 1)

Perl Best Practices рекомендует использовать вместо него reverse.

Но операция была бы гораздо более понятной, если бы вы написали:
@sorted_results = обратная сортировка @unsorted_results;

Однако я не нашел способа, чтобы подсорты работали в противоположных направлениях.

Очевидно, я могу сказать perlcritic игнорировать это, но я хотел бы знать, как достичь того, что мне нужно, и сделать perlcritic счастливым.

Ответы [ 3 ]

9 голосов
/ 23 февраля 2012

Perl :: Critic иногда будет больше интересоваться точным воспроизведением PBP, чем представлением хорошей политики, а некоторые из Perl Best Practices плохо выдерживают.Например, теперь крайне устаревшая Miscellanea :: RequireRcsKeywords по-прежнему включена по умолчанию.

Политики Perl :: Critic не должны рассматриваться как канонические.Им не хватает возможности сделать субъективный анализ, чтобы решить, действительно ли «исправление» приведет к увеличению сложности, особенно когда уровень серьезности падает, а выгоды становятся все более и более узкими. BuiltinFunctions :: ProhibitReverseSortBlock является политикой «косметического» уровня и прямо попадает в эту категорию.

Хотя кто-то может пропустить $b cmp $a и прочитать его задом наперед, понять его сразу не сложноПосмотрим, не стоит ли перепутывать весь массив впоследствии, и, конечно, не стоит искажать ваш блок сортировки, чтобы соответствовать ограничениям анализа политики.Их решение не изменять поведение по умолчанию, чтобы ограничить политику простыми блоками сортировки, является неверным IMO.Ваш блок сортировки явно выходит за рамки написанной политики и срабатывает только потому, что реализация политики Perl :: Critic ограничена.

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

Помните, что смысл не в том, чтобы быть счастливым perlcritic, дело в том, чтобы написать лучший код.

4 голосов
/ 22 февраля 2012

Я согласен с комментарием tchrist, но принимаю ваш вопрос по номинальной стоимости:

1) используйте ## no critic

my @unit_indices = sort {   ## no critic (ReverseSortBlock)
    $units{$b}[0] <=> $units{$a}[0] 
        or
    $a cmp $b
} keys %units;

2) Используйте .perlcriticrc файл

[-BuiltinFunctions::ProhibitReverseSortBlock]

3) Измените смысл вашего сравнения

my @unit_indices = sort { 
    -($units{$a}[0] <=> $units{$b}[0])
        or
    $a cmp $b
} keys %units;

my @unit_indices = sort { 
    -$units{$a}[0] <=> -$units{$b}[0])
        or
    $a cmp $b
} keys %units;
2 голосов
/ 23 февраля 2012

Не стесняйтесь использовать perlcritic, но не будьте его рабом.Весь смысл наличия perlcritic в том, чтобы иметь возможность выдавать предупреждения, которые имеют хорошие шансы ошибиться.

Он, безусловно, пытается поощрять использование reverse sort { $a <=> $b } сверх sort { $b <=> $a }, но этоздесь не обойтись.

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

...