簡體   English   中英

我如何 map 哈希數組?

[英]How do I map an array of hashes?

我有一個哈希數組:

arr = [ {:a => 1, :b => 2}, {:a => 3, :b => 4} ]

我想要實現的是:

arr.map{|x| x[:a]}.reduce(:+)

但我認為它有點難看,或者至少不像以下那樣優雅:

arr.map(&:a).reduce(:+)

后一個是錯誤的,因為散列中沒有稱為a的方法。

有沒有更好的寫法map{|x| x[:a]} map{|x| x[:a]}

您可以使用Struct制作實際的對象:

MyClass = Struct.new :a, :b
arr = [MyClass.new(1, 2), MyClass.new(3, 4)]
arr.map(&:a).reduce(:+)  #=> 4

或者,為了獲得更大的靈活性,可以使用OpenStruct

require 'ostruct'
arr = [OpenStruct.new(a: 1, b: 2), OpenStruct.new(a: 3, b: 4)]
arr.map(&:a).reduce(:+)  #=> 4

當然,這些都可以從現有的哈希值構造:

arr = [{ :a => 1, :b => 2 }, { :a => 3, :b => 4 }]

ss = arr.map { |h| h.values_at :a, :b }.map { |attrs| MyClass.new(*attrs) }
ss.map(&:a).reduce(:+)  #=> 4

oss = arr.map { |attrs| OpenStruct.new attrs }
oss.map(&:a).reduce(:+)  #=> 4

或者,對於更具創造性的功能性方法:

def hash_accessor attr; ->(hash) { hash[attr] }; end
arr = [{ :a => 1, :b => 2 }, { :a => 3, :b => 4 }]
arr.map(&hash_accessor(:a)).reduce(:+)  #=> 4

目前尚不清楚您所說的“更好”是什么意思,以及為什么您認為正確的版本是丑陋的。

你喜歡這個“更好”嗎?

arr.inject(0) { |sum, h| sum + h[:a] }

有一種方法,擴展Symbol

lib/core_extensions/symbol.rb (信用在這里

# frozen_string_literal: true

class Symbol
  def with(*args, &)
    ->(caller, *rest) { caller.send(self, *rest, *args, &) }
  end
end

然后,給出:

arr = [ {:a => 1, :b => 2}, {:a => 3, :b => 4} ]

你可以這樣做:

arr.map(&:[].with(:a)).reduce(:+)

解釋:要訪問任意鍵下的 hash 值,您調用Hash#[]方法。 當作為:[] (擴展)符號傳遞給Array#map時,您可以在此符號上調用.with(*args) ,有效地將參數(哈希鍵)向下傳遞給:[]方法。 享受。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM