【问题标题】:Perl6: Sorting Hash by Values and using kvPerl6:按值排序哈希并使用 kv
【发布时间】:2019-09-27 17:49:22
【问题描述】:

我正在查看以下数据(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 并不断,但没有一个工作:(

如何按值对这个哈希进行排序?

【问题讨论】:

  • @raiph sort(*.value) 返回一个序列,因此 .kv 将返回 $index, $element 而不是 $element-key, $element-value。您可以尝试将其转回哈希,例如sort(*.value).hash.kv 但随后哈希随机化会丢失排序。
  • @ugexe 谢谢。我已经删除了我的虚假评论。所以你的答案是正确的。 sort 返回 Seq。如果调用者是散列,则Seq 元素为Pairs。然后一个块可以使用.key.value。简单的!经验教训:1 我还是没能学到“Always test code, no exceptions”包含always这两个词 没有例外2 散列以随机顺序存储其密钥——“排序散列”是矛盾的。改为考虑“排序对”。 3 sort 不返回其调用者的排序版本。它以某种排序顺序返回该调用者的元素的Seq

标签: sorting hashmap comparator raku columnsorting


【解决方案1】:

.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 方法被映射到这些值上。)

【讨论】:

  • ` %files.sort(*.invert)».kv -> ($key,$value) {` 似乎最适合我。谢谢!
【解决方案2】:
my %hash = :a<z>, :b<y>, :c<x>;

for %hash.sort(*.value) {
    say $_.key;
    say $_.value;
}

【讨论】:

  • 我知道这只是一个例子,但只是为了说明替代方案——而不是say $_.key 可以只是say .key 甚至.key.say
猜你喜欢
  • 2010-10-20
  • 2015-10-23
  • 1970-01-01
  • 1970-01-01
  • 2014-10-27
  • 2016-11-21
  • 2011-07-07
  • 2017-03-24
  • 1970-01-01
相关资源
最近更新 更多