对哈希kv对进行排序

Сух*_*й27 7 sorting hashmap perl6

my %hash =
    two   => 2,
    three => 3,
    one   => 1,
;

for %hash.sort(*.key)>>.kv -> ($key, $value) {
    say "'$key' => '$value'";
}
Run Code Online (Sandbox Code Playgroud)

%hash.sort({.key})>>.kv等效于上面的排序?

为什么没有超级>>提示这种方法不起作用?

Bra*_*ert 10

sort方法返回一个列表.

因为调用.kv列表会返回一个index, Pair您不想要的列表列表; 你不能只是打电话.kv.因此,您必须通过在每个对象上调用方法来单独从列表中的Pair对象中提取键和值.kv,这样>>.kv做.

您也可以使用.map(*.kv).

>>.kv语法允许在多个线程传播工作,如果它是有道理这样做的实现.
(目前Rakudo只是以半随机顺序完成工作,以防止人们使用该功能错误)


通过使用子签名中的副词提取属性,可以使用另一种方法编写循环:

for %hash.sort -> (:$key, :$value) {
  say "'$key' => '$value'";
}

for %hash.sort -> $pair (:$key, :$value) {
  say $pair;
  say $key === $pair.key and $value === $pair.value; # True?
}

# :$key is short for :key($key)
for %hash.sort -> (:key($k), :value($v)) {
  say "'$k' => '$v'";
}
Run Code Online (Sandbox Code Playgroud)

这对于没有创建公共属性列表的方法的其他对象非常有用

class C { has $.a; has $.b; has $.c; has $!private-value }
my $c = 5;
my $obj = C.new(:a<A>,:b(1),:$c);

given $obj -> ( :$a, :b($b), :$c) ) {
  say "$a $b $c";
}

# ignore $.a by using an unnamed scalar
given $obj -> ( :a($), :$b, :$c ) { ... }

# places any unspecified public attributes in %others
given $obj -> ( :$a, :$b, *%others ) {
  .say for keys %others; # c?
}

# ignores any unspecified attributes
# useful to allow subclasses to add more attributes
# or to just drop any values you don't care about
given $obj -> ( :$a, :$b, *% ) { ... }

# fails because it doesn't handle the public c attribute
# in the sub-signature
given $obj -> ( :$a, :$b ) { ... }
Run Code Online (Sandbox Code Playgroud)

这只是签名可能的开始.

在子例程和方法签名中也允许以下所有内容,可选,并且对于此示例完全过度杀伤.它在用于限制可能的候选者的多子方法和多方法中非常有用.

for 'one' => 1, 1/3
->
  # Type is an alias to the object type
  ::Type Any $_ # Any is the default type requirement

  # the public attributes of the object
  (
    ::A-Type Any :key(   :numerator(   $a ) ),
    ::B-Type Any :value( :denominator( $b ) ) where $b >= 1,
  )
{
  my Type $obj = $_; # new variable declared as having the same type
  my A-Type $new-a = $a;
  my B-Type $new-b = $b;

  # could have used $_.^name or .^name instead of Type.^name
  # so you don't actually have to add the alias to the signature
  # to get the name of the arguments type
  say Type.^name, ' ', $_;
  say '  ', A-Type.^name, ' ', $a;
  say '  ', B-Type.^name, ' ', $b;
}
Run Code Online (Sandbox Code Playgroud)
Pair one => 1
  Str one
  Int 1
Rat 0.333333
  Int 1
  Int 3
Run Code Online (Sandbox Code Playgroud)

至于使用.sort({.key}),是的,这基本上是相同的,因为sort接受任何可调用的东西.

我想指出你甚至不需要提供参数,sort因为它的默认值甚至比你给它的更聪明.

Perl 6有许多创建和访问Callable事物的方法.所以以下任何一个都有效:

*.key
{ .key } # { $_.key }
-> $_ { .key } # basically what the previous line turns into
{ $^placeholder-var.key }
sub ($_) { .key }
&a-subroutine-reference # you would have to create the subroutine though
Run Code Online (Sandbox Code Playgroud)

此外,由于所有普通操作符实际上都是子例程,因此您可以在需要Callable的其他位置使用它们.(我想不出那个在那个地方工作的人)

&infix:<+> # the subroutines responsible for the numeric addition operator
&[+] # ditto

&prefix:<++>
&postfix:<++>

# etc
Run Code Online (Sandbox Code Playgroud)


Chr*_*oph 7

据我所知,两个版本之间的差异是使用带隐式$_参数的块而不是使用Whatever-Star,因此它们确实是等价的.

这是Perl,因此有多种方法可以做到:

*.key
{ .key }
{ $^arg.key }
-> $arg { $arg.key }
Run Code Online (Sandbox Code Playgroud)

为什么没有超级>>提示这种方法不起作用?

sort 将哈希强制转换为对的列表,这就是你将得到的:

say %hash.sort(*.key).perl;
# ("one" => "1", "three" => "3", "two" => "2")
Run Code Online (Sandbox Code Playgroud)

要摆脱这些对,你需要遍历列表并调用.kv每个对:

say %hash.sort(*.key)>>.kv.perl;
# (("one", "1"), ("three", "3"), ("two", "2"))

say %hash.sort(*.key).map(*.kv).perl;
# (("one", "1"), ("three", "3"), ("two", "2"))
Run Code Online (Sandbox Code Playgroud)

你可以Hash在打电话之前强迫.kv:

say %hash.sort(*.key).hash.kv.perl;
# ("one", "1", "three", "3", "two", "2")
Run Code Online (Sandbox Code Playgroud)

但这当然会破坏练习的目的,因为哈希排序不能依赖.

您可能已经注意到,根据您编写代码的准确程度,您将获得不同的结果.如果没有尾随.list,你得到的实际上是a Parcel而不是a List,但语义尚未最终确定.

请注意,即使返回的对象都使用简单的括号进行perlify,但有些是parcel,有些是列表,您可以通过调用来检查.WHAT.这仍然是一项进展中的工作.

还要注意其中一些变体的内括号,你可以通过调用来消除它们.flat.如果这样做,您可以使用-> $key, $valuefor循环的签名而不是-> ($key, $value)(或更明确地-> $anon ($key, $value))使用签名绑定来解包包裹.

而不是使用的.kv,你可以使用同样的方法来解开对对象,而不是:

for %hash.sort(*.key) -> (:$key, :$value) {
    say "'$key' => '$value'";
}
Run Code Online (Sandbox Code Playgroud)