Perl6: сортировка хэша по значениям и использование kv

Я смотрю на следующие данные (в JSON)

{
  "FValidation_pipelineMTHXT_v4.5.1_refLibV2": "concordance2/f",
  "FValidation_pipelineLPJL": "concordance2/c",
  "FCompetenceRuns": "concordance2/b",
  "FWGS": "concordance2/a",
  "Falidation_pipelineMTHXT": "concordance2/e",
  "FValidation_pipelineLPJL_v4.5.1_refLibV2": "concordance2/d"
}

и я пытаюсь отсортировать по хеш-значению

for %files.kv -> $key, $value {

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

for %files.sort.kv  -> ($key, $value) {

а также

for %files.sort: *.value.kv  -> ($key, $value) {

который был вдохновлен https://docs.perl6.org/routine/sort#(Map)_method_sort и так далее, но ни один из них не работает :(

Как мне отсортировать этот хеш по значению?


person con    schedule 09.05.2019    source источник
comment
@raiph sort(*.value) возвращает последовательность, и поэтому .kv вернет $index, $element, а не $element-key, $element-value. Вы можете попытаться превратить его обратно в хэш, например. sort(*.value).hash.kv, но тогда рандомизация хэша теряет сортировку.   -  person ugexe    schedule 10.05.2019
comment
@ugexe Спасибо. Я удалил свой фиктивный комментарий. Так что ваш ответ точный. sort возвращает Seq. Если инициатором является хэш, элементы Seq равны Pair. Затем блок может использовать .key и .value. Простой! Извлеченные уроки: 1 Мне все еще не удалось усвоить урок, что Всегда тестовый код, без исключений включает слова всегда и без исключений. 2 Хеш хранит свои ключи в случайном порядке - отсортированный хеш - это оксюморон. Вместо этого подумайте о сортированных парах. 3 sort не возвращает отсортированную версию своего вызывающего. Он возвращает Seq элементов этого вызывающего в некотором отсортированном порядке.   -  person raiph    schedule 10.05.2019


Ответы (2)


.kv возвращает плоскую последовательность.

my %h = (
  a => 3,
  b => 2,
  c => 1,
);

say %h.kv.perl;
# ("a", 3, "c", 1, "b", 2).Seq

Если вы его отсортируете, то вы сделаете это, не сохраняя ключ со связанным с ним значением.

say %h.kv.sort.perl;
# (1, 2, 3, "a", "b", "c").Seq

Итак, вы хотите отсортировать его перед разделением на пары.

# default sort order (key first, value second)
say %h.sort.perl;
# (:a(3), :b(2), :c(1)).Seq

say %h.sort: *.value;       # sort by value only (tied values are in random order)
# (:c(1), :b(2), :a(3)).Seq
say %h.sort: *.invert;      # sort by value first, key second
# (:c(1), :b(2), :a(3)).Seq
say %h.sort: *.kv.reverse;  # sort by value first, key second
# (:c(1), :b(2), :a(3)).Seq

После того, как он отсортирован, вы можете принять его как последовательность объектов Pair:

# default $_
for %h.sort: *.invert {
  say .key ~ ' => ' ~ .value
}

# extract as named attributes
for %h.sort: *.invert -> (:$key, :$value) {
  say "$key => $value"
}

# more explicit form of above
for %h.sort: *.invert -> Pair $ (:key($key), :value($value)) {
  say "$key => $value"
}

Или вы можете разделить пары после сортировки:
(Обратите внимание на двухуровневую структуру.)

say %h.sort(*.invert).map(*.kv).perl;
# (("c", 1).Seq, ("b", 2).Seq, ("a", 3).Seq).Seq
say %h.sort(*.invert)».kv.perl;
# (("c", 1).Seq, ("b", 2).Seq, ("a", 3).Seq).Seq

# default $_
for %h.sort(*.invert).map(*.kv) {
  say .key ~ ' => ' ~ .value
}

# extract inner positional parameters
for %h.sort(*.invert).map(*.kv) -> ($k,$v) {
  say "$k => $v"
}

# `».kv` instead of `.map(*.kv)`
for %h.sort(*.invert)».kv -> ($k,$v) {
  say "$k => $v"
}

Вы даже можете сгладить его после того, как разделите парные объекты.

say %h.sort(*.invert).map(*.kv).flat.perl;
# ("c", 1, "b", 2, "a", 3).Seq
say %h.sort(*.invert)».kv.flat.perl;
# ("c", 1, "b", 2, "a", 3).Seq

for %h.sort(*.invert).map(*.kv).flat -> $k, $v {
  say "$k => $v"
}

for %h.sort(*.invert)».kv.flat -> $k, $v {
  say "$k => $v"
}

(Обратите внимание, что ».method отображает только один вызов метода. Для сопоставления более двух вам понадобится ».method1».method2 или просто используйте карту .map(*.method1.method2).
Итак, в ».kv.flat выше значениям сопоставляется только метод .kv.)

person Brad Gilbert    schedule 10.05.2019
comment
`% files.sort (*. invert)». kv - ›($ key, $ value) {` кажется мне лучшим вариантом. Спасибо! - person con; 10.05.2019

person    schedule
comment
Я знаю, что это всего лишь пример, но просто чтобы отметить альтернативы - вместо say $_.key можно просто say .key или даже .key.say. - person Curt Tilmes; 10.05.2019