Archive for category arrays

Converting a Map to a List in Java 8, Groovy and Ruby

Some days ago I was developing a task on a Gradle project and I faced with a situation where I had to convert a Map < String, List < String >> to List < Pair >, each pair containing the key and one element from the List<String>.

I decided to compare the solution in three different languages: Java 8 (using lambdas and the Streams API), Groovy and Ruby to see how concise and expressive they would be. Then, I created the Groovy code and it looked like this:

#!/usr/bin/env groovy

def map = ["a" : ["1", "2", "3"], "b" : ["4", "5", "6"], "c" : ["7"]]

println map.collectMany { key, values -> values.collect {value -> [key, value]}}

Running the above code, the result is below:

[[a, 1], [a, 2], [a, 3], [b, 4], [b, 5], [b, 6], [c, 7]]

The Ruby version looked like this:

#!/usr/bin/env ruby

map = { "a" => ["1", "2", "3"], "b" => ["4", "5", "6"], "c" => ["7"] }

p map.collect {|key, values| values.map {|value| [key, value] } }.flatten(1)

The Ruby program generated the following output:

[["a", "1"], ["a", "2"], ["a", "3"], ["b", "4"], ["b", "5"], ["b", "6"], ["c", "7"]]

Below is the Java 8 version, using lambdas, Streams and the Collectors API:

        
        Map> values = new HashMap<>();
        values.put("a", Arrays.asList("1", "2", "3"));
        values.put("b", Arrays.asList("4", "5", "6"));
        values.put("c", Collections.singletonList("7"));

        final List result = values
                .entrySet()
                .stream()
                .collect(ArrayList::new,
                        (pairs, entry) -> pairs.addAll(entry
                                .getValue()
                                .stream()
                                .map(value -> new Pair(entry.getKey(), value))
                                .collect(Collectors.toList())),
                        List::addAll);

private static class Pair {

    private final String first;
    private final String second;

    public Pair(String first, String second) {
        this.first = first;
        this.second = second;
    }

    @Override
    public String toString() {
        return "Pair{first='" + first + "', second='" + second + "'}";
    }
}

Running the Java 8 version produced the following output:

[Pair{first='a', second='1'}, Pair{first='a', second='2'}, 
Pair{first='a', second='3'}, Pair{first='b', second='4'}, 
Pair{first='b', second='5'}, Pair{first='b', second='6'}, 
Pair{first='c', second='7'}]

The Groovy and Ruby version are very expressive and concise. Note the use of the collectMany method on the Groovy version and the use of the flatten method on the Ruby version to flatten the result list into a single list of pairs.
The Java 8 version made use of the collect method of the Stream API, to collect the results in a list of Pair instances, each one holding the key and value of each element from the List< String >.

What do you think about this comparison? Leave your comments here!

Tags: , , , , , , ,

Minimum difference puzzle in Ruby

Folks, here we are for another puzzle from Javalobby:

Given two arrays, sorted and exactly the same length, write a function that finds a pair of numbers – one from each of the arrays – such that the difference between both is as small as possible.

Suppose our input arrays are [1,2,3,4,5] and [6,7,8,9,10]. Below is my solution in Ruby, it’s a one liner code :-):

[1,2,3,4,5].product([6,7,8,9,10]).map {|x, y| [x, y, (x-y).abs]}.sort { |a, b| a.last<=> b.last }.first.take(2)

The output is [5, 6].

Have another solution? Leave your comments here!

Tags: , , , , , , ,

Balancing arrays puzzle in Ruby

Here we are for another puzzle from Javalobby:

Given an array of numbers, return the index at which the array can be balanced by all numbers on the left side add up the the sum of all numbers of the right side.

For example, an array with [1,5,6,7,9,10] can be balanced by splitting the array at position 4

Here is the solution in Ruby:

v=[1,5,6,7,9,10];sum = v.reduce(:+);count=0;index = (0...v.size).detect { |i| count += v[i]; count * 2 == sum};index == nil ? nil : index + 1

The input array [1,5,6,7,9,10] will split the array at position 4, as stated above.

Any other solutions? Drop comments here 🙂

Tags: , , , , , , ,