Accessing the values in an array of lists of pairs
It's always important to make your data structures right. In this case, they don't feel right, but I guess you are forced to use that format. In any case, I would solve it like this:
for @products.map( { |(.[0].value, .[1].value) } ) -> $name, $price {
In words: map the list with pairs to a Slip (prefix |
) with just the values of the pairs, and feed that into $name
and $price
two elements at a time. Perhaps better readable would be:
for @products.map( { (.[0].value, .[1].value).Slip } ) -> $name, $price {
For the data given, you can use this sub-signature:
for @products -> @ ( :$name, :$price ) {
say "$name: USD$price"
}
So this expects a single unnamed listy argument @
.
It then expounds upon that by saying it contains two named values.
(This works because you have them as Pair objects.)
Really what you had was very close to working, all you had to do was coerce to a Hash.
for @products -> $x { say $x.hash{"name"} ~ ": USD" ~ $x.hash{"price"} }
for @products -> Hash() $x { say $x{"name"} ~ ": USD" ~ $x{"price"} }
Personally if I were going to do a lot of work with this data I would create an ecosystem for it.
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;
If you didn't like the &
you could create a constant alias to the sub.
…
constant from-JSON-list =
our sub from-JSON-list ( @ (:$name, :$price) ) {
::?CLASS.new( :$name, :$price )
}
…
@products .= map: Product::from-JSON-list;
Since raku OO is so lightweight, you could use a class which is a great way to manage non-uniform data structures:
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" , price => "600"),
);
.say for @products;
#samsung s6: USD600
#samsung s6: USD600