I want to put objects together beautifully with ruby.

Asked 2 years ago, Updated 2 years ago, 45 views

[
  {
    : 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

2022-09-30 20:18

4 Answers

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.


2022-09-30 20:18

 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.


2022-09-30 20:18

 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 }}


2022-09-30 20:18

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]}]


2022-09-30 20:18

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.