访问成对列表数组中的值

问题描述

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."

我还想使用.kv方法以及$key$val进行迭代,如下所示:

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

# That gives a "Malformed parameter" error

我已经查看了Raku文档,但是文档中没有提到这种特殊情况。怎么做? 欢迎使用其他方法或即兴修改代码。

解决方法

正确设置数据结构始终很重要。在这种情况下,他们感觉不合适,但是我想您不得不使用这种格式。无论如何,我都会这样解决:

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

换句话说:将成对的列表映射到仅包含成对值的Slip(前缀|),然后一次将其馈送到$name$price两个元素中。也许更好的可读性是:

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

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

for @products -> @ ( :$name,:$price ) {
  say "$name: USD$price"
}

因此,这需要一个未命名的列表自变量@
然后通过说它包含两个命名值对此进行阐述。
(这很有用,因为您将它们作为对对象。)


真的,您的工作已经非常接近了,您所要做的就是强迫使用Hash。

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

for @products -> Hash() $x { say $x{"name"} ~ ": USD" ~ $x{"price"} }

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

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;

如果您不喜欢&,则可以为该子对象创建一个常量别名。

…

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

…

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

由于raku OO非常轻巧,因此您可以使用一个类,这是管理非均匀数据结构的好方法:

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

    method gist { "$.name: USD$.price" }
}

my @products = ( 
    Product.new(name => "samsung s6",price => "600"),Product.new(name => "samsung s6",);
.say for @products;

#samsung s6: USD600
#samsung s6: USD600
,

已经有了很好的答案。布拉德(Brad)的Hash()强制解决方案真是太棒了!

但是感觉好像需要另一个答案。没有人直接讨论您使用.kv进行键/值路由的冲动,以及出现的错误:

我还想使用.kv方法进行迭代……“格式错误的参数”

由于数据的性质,

.kv并没有帮助

您的数据如此.kv并不会帮助您到达需要去的地方。 (这就是为什么没人使用它的原因。)

为什么不呢?

这是您的数据:

    (name => "samsung s6",(name => "samsung s7",price => "700"),...

@products中的每个元素都是两个键/值对的子列表。

但是所有都没用

您真正想做的是丢弃现有的密钥,然后通过处理 value @products元素中的第一对的/ em>作为 new 键,第二对的 value 作为关联的 value >。

所以您最终会得到类似的东西:

("samsung s6" => "600"),("samsung s7" => "700"),

为此,您需要忘记.kv

相反,您需要适当地将.value例程与.pairup例程相结合。确实可行:

.say for @products[*;*]».value.pairup

显示:

samsung s6 => 600
samsung s7 => 700

让我们分解一下:

.say for @products[*;*]

显示:

name => samsung s6
price => 600
name => samsung s7
price => 700

有关[*;*]在做什么的说明,请参见my answer to How do I “flatten” a list of lists?

如前所述,这些键是无用的。我们希望每个Pair中的

.say for @products[*;*]».value

显示:

samsung s6
600
samsung s7
700

在这种情况下,»就像一个内部for循环或map。例如,我可以写:

.value.say for (do @$_ for @products[*;*])

但是只写一个字符»要容易得多。这样就摆脱了多余的括号,内部for结构以及其他结构。

最后,我们在末尾添加.pairup来配对列表的奇数和偶数元素;每个 odd 元素都将成为一个键,随后的(偶数)元素将成为关联的值。工作完成。

关于错误消息

错误消息包含。这是一个“弹出”符号,指明了解析器放弃的位置:

------> for @products -> $x⏏.kv

“格式错误的参数”一词在您的代码中呼出.

for @products -> $x.kv ...

$x已被解析为参数,或者至少是参数的开头。但是.又是什么呢?如果它是表达式的一部分,则可能正在调用方法调用,但是在这里您应该完成指定参数名称的操作。因此解析器无法运行。

,

出现错误的原因是您在List的{​​{1}}中构建了List的{​​{1}},但将其视为Pair的{​​{1}} es。

该代码最简单的解决方法是更新数据结构以匹配您的处理方式:

List

在这种情况下,Hash被评估为my @products = ( {name => "samsung s6",price => "600"},{name => "samsung s7",price => "700"} ); 构造函数。我认为这个问题是由于Raku {}Hash构造函数而不是特殊逗号引起的。

正如其他人所建议的那样,轻量级对象也可能有用,但是我认为了解如何构建您正在构建的东西很好。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...