1

我在 ruby​​ 中有一个数组哈希:

 @people = { "a" => ["john", "mark", "tony"], "b"=> ["tom","tim"], 
            "c" =>["jane"], "others"=>["rob", "ryan"] }

我想合并特定键值的数组中少于 3 个项目的所有键值对。它们应该被合并到名为“others”的键中,以大致给出以下结果

 @people = { "a" => ["john", "mark", "tony"], 
           "others"=> ["rob", "ryan", "tom", "tim", "jane"] }

使用以下代码是有问题的,因为哈希中不能存在重复的键值:

 @people = Hash[@people.map{|k,v| v.count<3 ? ["others",v] : [k,v]} ] %>

优雅地解决这个问题的最佳方法是什么?

4

6 回答 6

2

您几乎拥有它,问题是,正如您所注意到的,由于重复,您无法即时构建哈希的键/值对。解决此问题的一种方法是从您要构建的框架开始:

@people = @people.each_with_object({ 'others' => [ ] }) do |(k,v), h|
    if(v.length >= 3)
        h[k] = v
    else
        h['others'] += v
    end
end

或者,如果你不喜欢each_with_object,你可以:

h = { 'others' => [ ] }
@people.each do |k, v|
    # as above
end
@people = h

或者你可以使用几乎相同的结构inject(像往常一样注意从块中返回正确的东西)。

当然还有其他方法可以做到这一点,但这些方法非常清晰易懂;IMO 清晰度应该是您的首要目标。

于 2013-03-22T04:16:05.190 回答
1
Hash[ @people.group_by { |k,v| v.size < 3 ? 'others' : k }.
              map { |k,v| [k, v.flat_map(&:last)] } ]

=> {"a"=>["john", "mark", "tony"],
    "others"=>["tom", "tim", "jane", "rob", "ryan"]}
于 2013-03-22T06:50:10.387 回答
1

尝试:

>> @people = { "a" => ["john", "mark", "tony"], "b"=> ["tom","tim"], 
        "c" =>["jane"], "others"=>["rob", "ryan"] }

>> @new_people = {"others" => []}

>> @people.each_pair {|k,v| (v.size >= 3 && k!="others") ? @new_people.merge!(k=>v) : @new_people['others']+= v}    

>> @new_people
=> {"others"=>["rob", "ryan", "jane", "tom", "tim"], "a"=>["john", "mark", "tony"]}
于 2013-03-22T05:38:36.830 回答
0
@people[:others] = []
@people.each do |k, v|
  @people[:others] |= @people.delete(k) if v.size < 3
end
于 2013-03-22T04:22:22.187 回答
0
@people.inject({}) do |m, (k, v)|
  m[i = v.size >= 3 ? k : 'others'] = m[i].to_a + v
  m
end
于 2013-03-22T04:27:09.030 回答
0

那这个呢:

> less_than_three, others = @people.partition {|(key, values)| values.size >= 3 }
> Hash[less_than_three]
# => {"a"=>["john", "mark", "tony"]}
> Hash["others" => others.map {|o| o.last}.flatten]
# => {"others"=>["tom", "tim", "jane", "rob", "ryan"]}
于 2013-03-22T04:16:18.053 回答