【问题标题】:Sort a hash by key containing string format按包含字符串格式的键对哈希进行排序
【发布时间】:2017-07-27 12:43:51
【问题描述】:

我有一个包含如下字符串的哈希数组:

array = [
  {name: "Gad", color: "blue"},
  {name: "Lad", color: "red"},
  {name: "Mad", color: "green"},
  {name: "Sad", color: "blue"},
  {name: "Sad", color: "green"}
]

我试过了:

require 'pp'

array = [
  {name: "Gad", color: "blue"},
  {name: "Lad", color: "red"},
  {name: "Mad", color: "green"},
  {name: "Sad", color: "blue"},
  {name: "Sad", color: "green"}
]

pp array.partition { |x| x[:name] }

但结果对我来说是完全错误的:

[[{:name=>"Gad", :color=>"blue"},
  {:name=>"Lad", :color=>"red"},
  {:name=>"Mad", :color=>"green"},
  {:name=>"Sad", :color=>"blue"},
  {:name=>"Sad", :color=>"green"}],
 []]

预期结果如下:

[[{:name=>"Gad", :color=>"blue"}],
 [{:name=>"Lad", :color=>"red"}],
 [{:name=>"Mad", :color=>"green"}],
 [{:name=>"Sad", :color=>"blue"}, {:name=>"Sad", :color=>"green"}]]

【问题讨论】:

  • 不可能。您的预期结果不是有效的 Ruby 表达式。
  • 我的输出是用漂亮的打印(pp)完成的,这里有点混乱,对不起!
  • @Andrey Deineko 好的,我注意到了!
  • @all,现在我认为我的问题和预期更清楚了!

标签: ruby string sorting hash


【解决方案1】:
a.group_by { |hash| hash[:name] }.values
# [
#   [{:name=>"Gad", :color=>"blue"}],
#   [{:name=>"Lad", :color=>"red"}],
#   [{:name=>"Mad", :color=>"green"}],
#   [{:name=>"Sad", :color=>"blue"}, {:name=>"Sad", :color=>"green"}]
# ]

参考资料:

【讨论】:

  • 谢谢!这对我也有用!这个最优雅,太棒了!
【解决方案2】:

如果我可以这样说,具有相同名称和不同颜色的哈希数组可能不是您数据的最佳格式。

它包含冗余信息,查找缓慢且冗长。

您可以使用name 作为键和colors 的数组构建单个哈希:

array = [
  { name: 'Gad', color: 'blue' },
  { name: 'Lad', color: 'red' },
  { name: 'Mad', color: 'green' },
  { name: 'Sad', color: 'blue' },
  { name: 'Sad', color: 'green' }
]

colors = Hash.new { |h, k| h[k] = [] }

colors = array.each_with_object(colors) do |hash, colors|
  colors[hash[:name]] << hash[:color]
end

p colors
#=> {"Gad"=>["blue"], "Lad"=>["red"], "Mad"=>["green"], "Sad"=>["blue", "green"]}

【讨论】:

  • 是的,我同意,但目标是了解如何处理这种构造:散列数组 => 简单散列(这里恕我直言)或复杂散列(多个键/值与值是 arry例如)
  • 您还没有回答问题!看好你! SO 问题的数据结构通常很差,但没有人指出这一点并提出替代方案。
【解决方案3】:

使用group_by 可能更适合于此。例如:

array.group_by { |x| x[:name] }.map(&:last)
# => [[{:name=>"Gad", :color=>"blue"}], [{:name=>"Lad", :color=>"red"}], [{:name=>"Mad", :color=>"green"}], [{:name=>"Sad", :color=>"blue"}, {:name=>"Sad", :color=>"green"}]]

【讨论】:

  • 这里的编辑毫无意义,因为现在我们有一个重复的答案。尽管最初的答案比应该的更冗长,但它仍然有效。
【解决方案4】:

这使用Hash.update(又名merge!)的形式,该形式使用哈希来确定要合并的两个哈希中存在的键的值。

array.each_with_object({}) { |g,h| h.update(g[:name]=>[g]) { |_,o,n| o+n } }.values
  #=> [[{:name=>"Gad", :color=>"blue"}],
  #    [{:name=>"Lad", :color=>"red"}],
  #    [{:name=>"Mad", :color=>"green"}],
  #    [{:name=>"Sad", :color=>"blue"}, {:name=>"Sad", :color=>"green"}]] 

要创建@Eric 建议的数据结构,这将是:

array.each_with_object({}) { |g,h| h.update(g[:name]=>[g[:color]]) { |_,o,n| o+n } }
  #=> {"Gad"=>["blue"], "Lad"=>["red"], "Mad"=>["green"], "Sad"=>["blue", "green"]}

【讨论】:

    猜你喜欢
    • 2016-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-27
    • 2011-08-12
    • 2017-05-13
    • 2011-10-30
    • 1970-01-01
    相关资源
    最近更新 更多