1

私はルビーの配列のハッシュを次のように持っています:

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

特定のキー値の配列に3つ未満のアイテムがあるすべてのキー値ペアをマージしたいと思います。それらを「その他」と呼ばれるキーにマージして、おおよその結果を得る必要があります。

 @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

お気づきのように、問題は、重複が原因でハッシュのキーと値のペアをその場で構築できないことです。問題を回避する1つの方法は、構築しようとしているもののスケルトンから始めることです。

@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

試す:

>> @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 に答える
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 に答える
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 に答える
0
@people[:others] = []
@people.each do |k, v|
  @people[:others] |= @people.delete(k) if v.size < 3
end
于 2013-03-22T04:22:22.187 に答える