Babak Babak - 3 months ago 9
Ruby Question

Challenge: combine into an array only sequential keys of specific value in Ruby

I want a function that takes parameters like this

list = [{a:1},{a:2},{b:3},{b:4},{c:5},{a:6}]
key = :a
combine_only_sequential_occurances_of_specific_key(list,key)


and would return this

[{a:[1,2],{b:3},{b:4},{c:5},{a:6}]


Basically, combine a list of key/value pairs that occur sequentially, but limited only to a specific key (or if you like, a set of keys) and preserve order.

Answer

Thanks to the power of Enumerable, this is a rather easy task:

def combine_only_sequential_occurances_of_specific_key(list, *keys)
  list.
    chunk {|h| if keys.include?(k = h.keys.first) then k else :_alone end }.
      # split into chunks by key
    map {|k, hs| if k == :_alone || hs.size == 1 then hs.first else {k => hs.map(&:values).reduce(:concat)} end}
      # transform into hash from key to "sum" (i.e. concatenation) of the values
end

list = [{a: 1}, {a: 2}, {b: 3}, {b: 4}, {c: 5}, {a: 6}]
key = :a
combine_only_sequential_occurances_of_specific_key(list, key)
# => [{a: [1, 2]}, {b: 3}, {b: 4}, {c: 5}, {a: 6}]