【问题标题】:How to merge array index values and create a hash如何合并数组索引值并创建哈希
【发布时间】:2013-06-26 10:46:15
【问题描述】:

我正在尝试通过使用一些匹配将数组转换为哈希。在将数组转换为哈希之前,我想像这样合并值

 "Desc,X1XXSC,C,CCCC4524,xxxs,xswd"

并从中创建一个哈希。规则是,数组的第一个值是 Hash 中的键,在数组中有重复的键,对于这些键我需要合并值并将其放在一个键下。 “描述:”是键。我的程序是这样的。

 p 'test sample application'
 str = "Desc:X1:C:CCCC:Desc:XXSC:xxxs:xswd:C:4524"
 arr = Array.new
 arr = str.split(":")
 p arr
 test_hash = Hash[*arr]
 p test_hash

我找不到解决办法。如果哪位能指导一下,不胜感激。

【问题讨论】:

  • 描述合并值的规则
  • 等一下我会编辑

标签: ruby


【解决方案1】:

Facets 的函数式方法:

require 'facets'
str.split(":").each_slice(2).map_by { |k, v| [k, v] }.mash { |k, vs| [k, vs.join] }
#=> {"Desc"=>"X1XXSC", "C"=>"CCCC4524", "xxxs"=>"xswd"}

并不是说没有 Facets 就无法做到,而是因为核心中缺少一些基本抽象,所以需要更长的时间:

Hash[str.split(":").each_slice(2).group_by(&:first).map { |k, gs| [k, gs.map(&:last).join] }]
#=> {"Desc"=>"X1XXSC", "C"=>"CCCC4524", "xxxs"=>"xswd"}

【讨论】:

  • 我们又做了一次,我的each_with_object vs. 你的功能方法:)
  • @Sergio: 是的,我注意到了 ;-) 现在我们需要另一个 inject,另一个 each 并且我们有通常的嫌疑人再次围捕 :-) 如果我们有 @核心中的 987654327@ 我认为不会有任何讨论,但Hash[...] 是如此丑陋和反 OOP 我知道没有人愿意使用它。
【解决方案2】:

@Sergio Tulentsev 解决方案的一个小变化:

str = "Desc:X1:C:CCCC:Desc:XXSC:xxxs:xswd:C:4524"
str.split(':').each_slice(2).each_with_object(Hash.new{""}){|(k,v),h| h[k] += v}
# => {"Desc"=>"X1XXSC", "C"=>"CCCC4524", "xxxs"=>"xswd"}
  • str.split(':') 产生一个数组;无需使用arr = Array.new 进行初始化

  • each_slice(2) 将此数组的元素两两提供给一个块或它后面的方法,就像在这种情况下一样。

  • each_with_object 获取这两个元素(作为一个数组)并将它们与一个对象一起传递给一个块,该对象由以下人员指定:

  • (Hash.new{""}) 这个对象是一个具有特殊行为的空 Hash:当一个键 not 找到时,它会返回一个值 ""(而不是通常的 nil)。

  • {|(k,v),h| h[k] += v} 这是完成所有工作的代码块。它获取包含两个元素的数组并将其解构为两个字符串,分配给 k 和 v;特殊哈希分配给 h。 h[k] 向哈希查询键“Desc”的值。它以“”响应,并添加了“X1”。重复此操作,直到处理完所有元素。

【讨论】:

  • 非常感谢。似乎我有很多关于 ruby​​ 的知识。谢谢你:)
  • @Kalanamith 添加了分步说明。
【解决方案3】:

我相信您正在这里寻找each_sliceeach_with_object

str = "Desc:X1:C:CCCC:Desc:XXSC:xxxs:xswd:C:4524"
hash = str.split(':').each_slice(2).each_with_object({}) do |(key, value), memo|
  memo[key] ||= ''
  memo[key] += value
end

hash # => {"Desc"=>"X1XXSC", "C"=>"CCCC4524", "xxxs"=>"xswd"}

【讨论】:

  • 非常感谢。我将研究 each_slice 和 each_with_object 的作用。我还在学习核心 ruby​​
【解决方案4】:

Enumerable#slice_before 是个好方法。

str = "Desc:X1:C:CCCC:Desc:XXSC:xxxs:xswd:C:4524"
a = ["Desc","C","xxxs"] # collect the keys in a separate collection.
str.split(":").slice_before(""){|i| a.include? i}
# => [["Desc", "X1"], ["C", "CCCC"], ["Desc", "XXSC"], ["xxxs", "xswd"], ["C", "4524"]]
hsh = str.split(":").slice_before(""){|i| a.include? i}.each_with_object(Hash.new("")) do |i,h|
  h[i[0]] += i[1]
end
hsh
# => {"Desc"=>"X1XXSC", "C"=>"CCCC4524", "xxxs"=>"xswd"}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-26
    • 1970-01-01
    • 2019-03-03
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    • 2020-07-24
    相关资源
    最近更新 更多