patternrubyMinor
Transforming an array in Ruby
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:
Would become:
I came up with the following solution.
How would you go about solving this problem?
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:
That's how I'd write it:
- From the moment you write
hash[n] += 1, your solution is not functional anymore.
each_with_objectis also imperative, for FP you should usereduce.
reduceworks well with linked lists, not so well for generating new arrays. In any case,reduceis 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.