9

我有一个简单的数组

array = ["apple", "orange", "lemon"] 

array2 = [["apple", "good taste", "red"], ["orange", "bad taste", "orange"], ["lemon" , "no taste", "yellow"]]

每当数组中的元素与array2中每个元素的第一个元素匹配时,我如何转换为这个哈希?

hash = {"apple" => ["apple" ,"good taste", "red"],
        "orange" => ["orange", "bad taste", "orange"], 
        "lemon" => ["lemon" , "no taste", "yellow"] }

我对红宝石很陌生,花了很多钱来做这个操作,但没有运气,有什么帮助吗?

4

5 回答 5

14

如果键和对之间的映射顺序应该基于 中的第一个元素array2,那么您根本不需要array

array2 = [
  ["apple", "good taste", "red"],
  ["lemon" , "no taste", "yellow"],
  ["orange", "bad taste", "orange"]
]

map = Hash[ array2.map{ |a| [a.first,a] } ]
p map
#=> {
#=>   "apple"=>["apple", "good taste", "red"],
#=>   "lemon"=>["lemon", "no taste", "yellow"],
#=>   "orange"=>["orange", "bad taste", "orange"]
#=> }

如果你想用来array选择元素的子集,那么你可以这样做:

# Use the map created above to find values efficiently
array = %w[orange lemon]
hash  = Hash[ array.map{ |val| [val,map[val]] if map.key?(val) }.compact ]
p hash
#=> {
#=>   "orange"=>["orange", "bad taste", "orange"],
#=>   "lemon"=>["lemon", "no taste", "yellow"]
#=> }

如果请求不存在于 中的键,则代码确保不会出现问题,if map.key?(val)并且会及时执行。compactarrayarray2O(n)

于 2012-06-08T04:30:52.660 回答
4

配对元组散列示例

fruit_values = [
  ['apple', 10],
  ['orange', 20],
  ['lemon', 5]
]

fruit_values.to_h
# => {"apple"=>10, "orange"=>20, "lemon"=>5} 

我决定将这个答案留给任何希望将成对元组转换为哈希的人。

虽然它与问题略有不同,但这是我登陆 Google 搜索的地方。由于键数组已经在元组中,它也与原始问题有点匹配。这也没有将密钥放入原始问题想要的值中,但老实说,我不会复制该数据。

于 2019-10-03T03:40:33.013 回答
3

这会给你想要的结果。

hash = {}

array.each do |element|
  i = array2.index{ |x| x[0] == element }
  hash[element] = array2[i] unless i.nil?
end
于 2012-06-08T04:17:07.450 回答
0

您也可以使用Array#to_h直接转换为Hash

array2 = [
  ["apple", "good taste", "red"],
  ["lemon" , "no taste", "yellow"],
  ["orange", "bad taste", "orange"]
]

map = array2.to_h { |items| [items.first, items] }

这将返回所需的:

{"apple"=>["apple", "good taste", "red"], "lemon"=>["lemon", "no taste", "yellow"], "orange"=>["orange", "bad taste", "orange"]}
于 2022-02-23T19:56:15.433 回答
-1

哦..我很想覆盖 rassoc

在 irb 上查看以下内容

class Array
  def rassoc obj, place=1
    if place
      place = place.to_i rescue -1
      return if place < 0
    end

    self.each do |item|
      next unless item.respond_to? :include? 

      if place
        return item if item[place]==obj
      else
        return item if item.include? obj
      end
    end

    nil
  end
end

array = ["apple", "orange", "lemon"] 
array2 = [["apple", "good taste", "red"], ["orange", "bad taste", "orange"], ["lemon" , "no taste", "yellow"]]

Hash[ array.map{ |fruit| [fruit, array2.rassoc(fruit, nil)]}]
# this is what you want

# order changed
array2 = [["good taste", "red", "apple"], ["no taste", "lemon", "yellow"], ["orange", "bad taste", "orange"]]

Hash[ array.map{ |fruit| [fruit, array2.rassoc(fruit, nil)]}]
# same what you want after order is changed
于 2012-06-08T06:11:43.500 回答