访问对列表数组中的值

Lar*_*een 7 hashmap raku

my @products = (
    (name => "samsung s6" , price => "600"),
    (name => "samsung s7" , price => "700"));

# for @products -> $x { say $x{"name"} ~ ": USD" ~ $x{"price"} };

# Desired output:
#
# samsung s6: USD600
# samsung s7: USD700

# Real output: An error:
#
# "Type List does not support associative indexing."
Run Code Online (Sandbox Code Playgroud)

我还想使用该.kv方法进行迭代, $key并且$val像这样:

for @products -> $x.kv -> $key,$val  { say $x{$key} ~ " " ~ $x{$val} };

# That gives a "Malformed parameter" error
Run Code Online (Sandbox Code Playgroud)

我查阅了 Raku 文档,但文档中没有提到这个特殊情况。怎么做?欢迎使用替代方法或对代码进行即兴创作。

Eli*_*sen 6

使您的数据结构正确始终很重要。在这种情况下,他们感觉不对,但我想您被迫使用该格式。无论如何,我会这样解决:

for @products.map( { |(.[0].value, .[1].value) } ) -> $name, $price {
Run Code Online (Sandbox Code Playgroud)

换句话说:将带有对的列表映射到|仅包含对值的Slip(前缀),并将其一次输入$name$price两个元素。也许更好的可读性是:

for @products.map( { (.[0].value, .[1].value).Slip } ) -> $name, $price {
Run Code Online (Sandbox Code Playgroud)


Bra*_*ert 5

对于给定的数据,您可以使用此子签名:

for @products -> @ ( :$name, :$price ) {
  say "$name: USD$price"
}
Run Code Online (Sandbox Code Playgroud)

所以这需要一个未命名的 listy 参数@
然后它通过说它包含两个命名值来阐述这一点。
(这是有效的,因为您将它们作为 Pair 对象。)


真的,你所拥有的非常接近工作,你所要做的就是强制使用哈希。

for @products -> $x { say $x.hash{"name"} ~ ": USD" ~ $x.hash{"price"} }

for @products -> Hash() $x { say $x{"name"} ~ ": USD" ~ $x{"price"} }
Run Code Online (Sandbox Code Playgroud)

就个人而言,如果我要使用这些数据做很多工作,我会为它创建一个生态系统。

class Product {
  has $.name;
  has $.price;

  our sub from-JSON-list ( @ (:$name, :$price) --> ::?CLASS ) {
    ::?CLASS.new( :$name, :$price )
  }

  method gist ( --> Str ) { "$.name: USD$.price" }
}


@products .= map: &Product::from-JSON-list;

.say for @products;
Run Code Online (Sandbox Code Playgroud)

如果你不喜欢&你可以为 sub 创建一个常量别名。

…

  constant from-JSON-list =
  our sub from-JSON-list ( @ (:$name, :$price) ) {
    ::?CLASS.new( :$name, :$price )
  }

…

@products .= map: Product::from-JSON-list;
Run Code Online (Sandbox Code Playgroud)