HiveBrain v1.2.0
Get Started
← Back to all entries
patternrubyMinor

Transforming an array in Ruby

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
arraytransformingruby

Problem

I watched a presentation by Dave Thomas on Elixir where he gave an example problem that he solved using functional programming. He mentioned using Ruby to solve the same problem, but did not show an example. I decided to give it a try. The problem goes something like this:

For a list (Ruby doesn't have lists, but for our purposes an Array is close enough) of n numbers, create a new list where unique numbers are represented once, and repeated numbers are represented by a tuple (again, Ruby doesn't have tuples, but for our purposes a Hash or an Array would do) where the first element is the number itself, and the second is its count.

For Example, the following list:

[ 1, 2, 2, 2, 3, 4, 4, 5, 6, 6, 6, 6 ]


Would become:

[ 1, {2, 3}, 3, {4, 2}, 5, {6, 3} ]


I came up with the following solution.

list = [ 1, 2, 2, 2, 3, 4, 4, 5, 6, 6, 6, 6 ]
list.each_with_object(Hash.new(0)) { |n, hash| hash[n] += 1 }.map { |k, v| v > 1 ? { k => v } : k }
#=> [ 1, {2 => 3}, 3, {4 => 2}, 5, {6 => 3} ]


How would you go about solving this problem?

Solution

Some notes:

  • From the moment you write hash[n] += 1, your solution is not functional anymore.



  • each_with_object is also imperative, for FP you should use reduce.



  • reduce works well with linked lists, not so well for generating new arrays. In any case, reduce is a generic abstraction, there is a more specific one to the problem at hand: Enumerable#chunk.



That's how I'd write it:

xs.chunk(&:itself).map { |y, ys| ys.size == 1 ? y : {y => ys.size} }

Code Snippets

xs.chunk(&:itself).map { |y, ys| ys.size == 1 ? y : {y => ys.size} }

Context

StackExchange Code Review Q#86787, answer score: 4

Revisions (0)

No revisions yet.