我有一个如下所示的数组:
[
{"timestamp" => 1347119549, "category" => nil},
{"timestamp" => 1347119547, "category" => "Monkeys"},
{"timestamp" => 1347119543, "category" => nil},
{"timestamp" => 1347119542, "category" => "Monkeys"}
]
我希望按时间戳(降序)对其进行排序,除非它的类别不是nil,在这种情况下它应该与它的“兄弟”一起出现,即使它比未分类的条目“更旧”。我需要对这个数组进行排序,所以看起来像这样:
[
{"timestamp" => 1347119549, "category" => nil},
{"timestamp" => 1347119547, "category" => "Monkeys"},
{"timestamp" => 1347119542, "category" => "Monkeys"},
{"timestamp" => 1347119543, "category" => nil}
]
我想弄清楚如何使用group_by
和sort
来获得正确的结果,但没有成功。
答案 0 :(得分:2)
require 'pp'
ar = [
{"timestamp" => 1347119549, "category" => nil},
{"timestamp" => 1347119547, "category" => "Monkeys"},
{"timestamp" => 1347119543, "category" => nil},
{"timestamp" => 1347119542, "category" => "Monkeys"}
]
pp ar.group_by{|h| h['category'] ? h['category'] : h['timestamp']}.
map{|k,v| v.sort_by{|h| -h['timestamp']}}.
sort_by{|a| -a[0]['timestamp']}.flatten
# >> [{"timestamp"=>1347119549, "category"=>nil},
# >> {"timestamp"=>1347119547, "category"=>"Monkeys"},
# >> {"timestamp"=>1347119542, "category"=>"Monkeys"},
# >> {"timestamp"=>1347119543, "category"=>nil}]
require 'pp'
a = [
{"timestamp"=>1347119549, "category"=>nil},
{"timestamp"=>1347119547, "category"=>"Monkeys"},
{"timestamp"=>1347119543, "category"=>nil},
{"timestamp"=>1347119542, "category"=>"Monkeys"},
{"timestamp"=>1347119548, "category"=>"Dog"},
{"timestamp"=>1347119544, "category"=>"Dog"}
]
pp a.group_by{|h| h['category'] ? h['category'] : h['timestamp']}.
map{|k,v| v.sort_by{|h| -h['timestamp']}}.
sort_by{|a| -a[0]['timestamp']}.flatten
# >> [{"timestamp"=>1347119549, "category"=>nil},
# >> {"timestamp"=>1347119548, "category"=>"Dog"},
# >> {"timestamp"=>1347119544, "category"=>"Dog"},
# >> {"timestamp"=>1347119547, "category"=>"Monkeys"},
# >> {"timestamp"=>1347119542, "category"=>"Monkeys"},
# >> {"timestamp"=>1347119543, "category"=>nil}]
答案 1 :(得分:1)
看起来有点难看,但它有效:
a = [
{"timestamp"=>1347119549, "category"=>nil},
{"timestamp"=>1347119547, "category"=>"Monkeys"},
{"timestamp"=>1347119543, "category"=>nil},
{"timestamp"=>1347119542, "category"=>"Monkeys"},
{"timestamp"=>1347119548, "category"=>"Dog"},
{"timestamp"=>1347119544, "category"=>"Dog"}
]
groups = a.sort_by {|h| -h['timestamp']}.group_by {|h| h['category']}
sorted = (groups.delete(nil) || []) + groups.values
sorted = sorted.sort_by{|i| i.is_a?(Hash) ? -i['timestamp'] : -i.first['timestamp']}.flatten
这会在sorted
中为您提供以下内容:
[
{"timestamp"=>1347119549, "category"=>nil},
{"timestamp"=>1347119548, "category"=>"Dog"},
{"timestamp"=>1347119544, "category"=>"Dog"},
{"timestamp"=>1347119547, "category"=>"Monkeys"},
{"timestamp"=>1347119542, "category"=>"Monkeys"},
{"timestamp"=>1347119543, "category"=>nil}
]
我先按'timestamp'
排序,以便稍后对这些组进行排序。
按'category'
分组后,我会移动数组中nil
类别的值。在这里,我使用(groups.delete(nil) || [])
以防nil
组为空。
现在可以再次按'timestamp'
排序,数组的timestamp
为其第一个哈希的timestamp
。
最后flatten
为我们提供了所需的数组。
答案 2 :(得分:1)
此处需要的技巧是分配唯一组而不是nil。您只需创建一个通用的Ruby Object
即可。
orig = [
{"timestamp"=>1347119549, "category"=>nil},
{"timestamp"=>1347119547, "category"=>"Monkeys"},
{"timestamp"=>1347119543, "category"=>nil},
{"timestamp"=>1347119542, "category"=>"Monkeys"}]
# The "tricky bit"
grouped = orig.group_by { |x| x["category"] ? x["category"] : Object.new }
# Sort the siblings within the groups (note negation causes reverse order)
grouped.values.each { |siblings| siblings.sort_by! { |a| -a["timestamp"] } }
# Sort the list by first (i.e. "best" sort order) timestamp in each group
sorted_groups = grouped.sort_by { |group_id,siblings| -siblings.first["timestamp"] }
# Remove group ids and flatten the list:
result = sorted_groups.map { |group_id,siblings| siblings }.flatten
=> [
{"timestamp"=>1347119549, "category"=>nil},
{"timestamp"=>1347119547, "category"=>"Monkeys"},
{"timestamp"=>1347119542, "category"=>"Monkeys"},
{"timestamp"=>1347119543, "category"=>nil}
]
答案 3 :(得分:1)
只需使用您尝试过的工具即可完成。
首先通过tiemstamp sort
整个数组,然后使用group_by
按类别分配它们:
arr = [
{'timestamp' => 1347119549, 'category' => nil},
{'timestamp' => 1347119547, 'category' => 'Monkeys'},
{'timestamp' => 1347119543, 'category' => nil},
{'timestamp' => 1347119542, 'category' => 'Monkeys'},
{'timestamp' => 1347119541, 'category' => nil},
{'timestamp' => 1347119548, 'category' => nil},
{'timestamp' => 1347119545, 'category' => nil},
]
sorted = arr.sort_by { |elem| 0 - elem['timestamp'] }
groups = sorted.group_by { |elem| elem['category'] or Object.new }
sorted = groups.values.flatten
puts sorted
<强>输出强>
{"timestamp"=>1347119549, "category"=>nil}
{"timestamp"=>1347119548, "category"=>nil}
{"timestamp"=>1347119547, "category"=>"Monkeys"}
{"timestamp"=>1347119542, "category"=>"Monkeys"}
{"timestamp"=>1347119545, "category"=>nil}
{"timestamp"=>1347119543, "category"=>nil}
{"timestamp"=>1347119541, "category"=>nil}
当然,你可以以可读性为代价来管理整个事情。
sorted = arr.sort_by { |elem| 0 - elem['timestamp'] }.group_by { |elem| elem['category'] or Object.new }.values.flatten