For example,
input = ['a','b','b','b','a','a','b','c','c']
output = ['a',['b','b','b'],['a','a'],'b',['c','c']]
Here, if there are more than one same elements then those are put into sub-array.
Can you please help me out?
For example,
input = ['a','b','b','b','a','a','b','c','c']
output = ['a',['b','b','b'],['a','a'],'b',['c','c']]
Here, if there are more than one same elements then those are put into sub-array.
Can you please help me out?
This solution uses a sneaky trick to prevent having to check if a list element is either a single element or an Array already. By doing [*list[-1]]
we make sure to always end up with an Array, regardless of whether the last element in the list
we are building was a single element (e.g., 'a'
) or an Array already (e.g., ['b','b']
). Then, we check if the first element of that Array (could be any element, they are all the same) is equal to the element of input
we are currently processing. If so, we append it to the created Array. Otherwise, we just append it to list
since it is different from the previous element.
input = ['a','b','b','b','a','a','b','c','c']
output = input.reduce([]) do |list, e|
last = [*list[-1]]
if last[0] == e
list[-1] = last << e
else
list << e
end
list
end
p output
# ["a", ["b", "b", "b"], ["a", "a"], "b", ["c", "c"]]
Alternatively, with checking specifically for the type of the element it would be something like this:
output = input.reduce([]) do |list, e|
last = list.last
if last.is_a? Array and last.include? e
last << e
elsif last == e
list[-1] = [last, e]
else
list << e
end
list
end
This was tested on Ruby 2.0, but it should run fine on 1.8.7 as well.
Ruby 1.9+ has Enumerable#chunk
, which will almost do what you want:
input.
chunk {|e| e }.
map(&:last).
map {|e| if e.size == 1 then e.first else e end }
For older versions of Ruby, Enumerable#chunk
is available in Marc-André Lafortunes backports
gem. Just add
require 'backports/1.9.2/enumerable/chunk'
on top.
I was under the impression that, this problem can be solved using slice_before
. But couldn't figured out. Finally Robert Klemme has guided me in the proper direction. Hope you guys would also like it.
input = ['a','b','b','b','a','a','b','c','c']
prev = nil
input.slice_before { |e| (e != prev).tap { prev = e } }.
map { |elem| elem.size == 1 ? elem.first : elem }
# => ["a", ["b", "b", "b"], ["a", "a"], "b", ["c", "c"]]