[
{
: id=>1,
—data=>1
},
{
: id=>1,
—data=>2
},
{
: id=>2,
—data=>1
},
{
: id=>2,
—data=>2
}
]
↓I want to do this
[
{
: id=>1,
—data=>[1,2]
},
{
: id=>2,
—data=>[1,2]
},
]
There are lots of loops and it doesn't work.
ruby
How about this?
objects=[
{
: id=>1,
—data=>1
},
{
: id=>1,
—data=>2
},
{
: id=>2,
—data=>1
},
{
: id=>2,
—data=>2
}
]
objects
.map {|h|[h[:id ], h[:data]]}
.group_by (&:first)
.map {|id,arr|{id:id,data:arr.map(&:last)}}
# =>[{:id=>1,:data=>[1,2]},{:id=>2,:data=>[1,2]}]
If you don't mind if it's a little difficult to read, you can write like this.
The number of loops is likely to decrease.
data_holder=Hash.new {|h,k|h[k]={id:k,data:[]}}
objects.each_with_object(data_holder) {|object,holder|
holder [ object [:id]][:data]<<object[:data]
}.values
Some patterns use tap
instead of each_with_object
.
Hash.new{|h,k|h[k]={id:k,data:[]}}.tap{|hash|
objects.each do|obj|
id,data=obj.values_at(:id,:data)
hash [id][:data]<<data
end
}.values
Try implementing it any way you like.
objects=[
{
: id=>1,
—data=>1
},
{
: id=>1,
—data=>2
},
{
: id=>2,
—data=>1
},
{
: id=>2,
—data=>2
}
]
objects
.group_by {|h|h[:id]}
.map {|k,h|{id:k,data:h.map {|h|h[:data]}}}
Please refer to Junichi Ito's code
I will also add a way not to array before group_by.
hash={}
array.each do|obj|
if hash [obj[:id]]
hash[obj[:id]]<obj[:data]
else
hash[obj[:id]]=[obj[:data]]
end
end
pp hash.to_a.map { | a | { id: a.first, data: a.last }}
I tried it too.
input = [
{
: id=>1,
—data=>1
},
{
: id=>1,
—data=>2
},
{
: id=>2,
—data=>1
},
{
: id=>2,
—data=>2
}
]
output = input.reduce({}) {|hash, item|
(hash[item[:id]]) ||= <<item[:data]
hash
}.map { | key, value | { id:key, data:value }
ppp output
# =>[{:id=>1,:data=>[1,2]},{:id=>2,:data=>[1,2]}]
© 2024 OneMinuteCode. All rights reserved.