简体   繁体   中英

How to find the key of the last array

I have a hash that has an array value:

some_attributes['variants']
# =>
# [
#   [["variantCode", "0715839001002"], ["sizeCode", "002"], ["sizeName", "XS"]],
#   [["variantCode", "0715839001003"], ["sizeCode", "003"], ["sizeName", "S"]],
#   [["variantCode", "0715839001004"], ["sizeCode", "004"], ["sizeName", "M"]],
#   [["variantCode", "0715839001005"], ["sizeCode", "005"], ["sizeName", "L"]]
# ]

I am expecting in a new array the keys of each "sizeName":

['XS', 'S', 'M', 'L']

I tried like this:

some_attributes['variants'[[['sizeName']]]]

some_attributes['variants'].select{|size| sizeName["sizeName"]}

But I can't find the solution. Any tricks?

some_attributes['variants'].map{|a| a[-1][1]}
#=> ["XS", "S", "M", "L"]

Where the first -1 is the index of the last of element of the 1st dimension.
And the second 1 is simply the second index of the 2nd demension,
-- which in this case, is in effect the same of another -1 / last index.

IE below is the same in effect:

some_attributes['variants'].map{|a| a[-1][-1]}
#=> ["XS", "S", "M", "L"]

To increase the legibility:

some_attributes['variants'].map{|a| a.last.last}
#=> ["XS", "S", "M", "L"]

Not only this notation is more intuitive, but it also runs faster, check iGian's Benchmark below:)

Looks like you could turn the variants into hashes.

some_attributes = {
  "variants" => [
    [["variantCode", "0715839001002"], ["sizeCode", "002"], ["sizeName", "XS"]],
    [["variantCode", "0715839001003"], ["sizeCode", "003"], ["sizeName", "S"]],
    [["variantCode", "0715839001004"], ["sizeCode", "004"], ["sizeName", "M"]],
    [["variantCode", "0715839001005"], ["sizeCode", "005"], ["sizeName", "L"]]
  ]
}

variants = some_attributes['variants'].map(&:to_h)
variants.map { |variant| variant['sizeName'] }
=> ["XS", "S", "M", "L"]

Then it's easier to do something like:

large_variant = variants.find { |variant| variant['sizeName'] == 'L' }
puts large_variant['variantCode']
# outputs:
# 0715839001005

Or to just get what you wanted, simply:

some_attributes['variants'].map { |a| a.last.last }
#=> ["XS", "S", "M", "L"]

Just out of curiosity:

some_attributes['variants'].map { |(_, _), (_, _), (_, e)| e }
#⇒ ["XS", "S", "M", "L"]

some_attributes['variants'].map(&:flatten).map(&:last)
#⇒ ["XS", "S", "M", "L"]

Just for fun, other option:

some_attributes["variants"].map(&:last).map(&:last)
#=> ["XS", "S", "M", "L"]

Also

some_attributes["variants"].transpose.last.transpose.last
#=> ["XS", "S", "M", "L"]

Or even a mix:

some_attributes["variants"].map(&:last).transpose.last
#=> ["XS", "S", "M", "L"]


A benchmark of the methods posted

require 'benchmark' n = 5000 Benchmark.bm do |x| x.report("tiw_____") { n.times { some_attributes['variants'].map{|a| a[-1][1]} } } x.report("kimmo___") { n.times { some_attributes['variants'].map { |a| a.last.last } } } x.report("Aleksei1") { n.times { some_attributes['variants'].map { |(_, _), (_, _), (_, e)| e } } } x.report("igian1__") { n.times { some_attributes["variants"].map(&:last).map(&:last) } } x.report("igian3__") { n.times { some_attributes["variants"].map(&:last).transpose.last } } x.report("igian2__") { n.times { some_attributes["variants"].transpose.last.transpose.last } } x.report("Aleksei2") { n.times { some_attributes['variants'].map(&:flatten).map(&:last) } } end

One result (each run results change a bit):

 # user system total real # tiw_____ 0.007577 0.000078 0.007655 ( 0.007709) # kimmo___ 0.003979 0.000086 0.004065 ( 0.004070) # Aleksei1 0.008227 0.000158 0.008385 ( 0.008542) # igian1__ 0.008080 0.000132 0.008212 ( 0.008220) # igian2__ 0.011956 0.000168 0.012124 ( 0.012571) # igian3__ 0.013975 0.000122 0.014097 ( 0.014261) # Aleksei2 0.054203 0.002921 0.057124 ( 0.059449)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM