问题
I have a 2 dimensional array
v = [ ["ab","12"], ["ab","31"], ["gh","54"] ]
The first element of the subarray of v will have repeating elements, such as "ab". I want to create a hash that puts the key as the first element of the subarray, and values as an array of corresponding second elements from v.
please advice.
Further, I want this, h={"ab"=>["12","31"],"gh"=>["54"]} and then I want to return h.values, such that the array [["12","31"],["54"]] is returned
回答1:
v.inject(Hash.new{|h,k|h[k]=[]}) { |h, (k, v)| h[k] << v ; h}
What it does:
inject (also called
reduce) is a fold. Wikipedia defines folds like this: "a family of higher-order functions that analyze a recursive data structure and recombine through use of a given combining operation the results of recursively processing its constituent parts, building up a return value".The block form of Hash.new takes two arguments, the hash itself and the key. If your default argument is a mutable object, you have to set the default this way, otherwise all keys will point to the same array instance.
In
inject's block, we get two arguments, the hash and the current value of the iteration. Since this is a two element array,(k, v)is used to destructure the latter into two variables.Finally we add each value to the array for its key and return the entire hash for the next iteration.
回答2:
v.inject({}) do |res, ar|
res[ar.first] ||= []
res[ar.first] << ar.last
res
end
回答3:
v = [ ["ab","12"], ["ab","31"], ["gh","54"] ]
This gets you a hash, where the keys are the unique first elements from the sub arrays.
h = v.inject({}) { |c,i| (c[i.first] ||= []) << i.last; c }
This turns that hash back into an array, just in case you need the array of arrays format.
arr = h.collect { |k,v| [k,v] }
来源:https://stackoverflow.com/questions/11715833/extracting-from-2-dimensional-array-and-creating-a-hash-with-array-values