1

I have list with Versions (Strings), I want to make List of List for version of every release

List<List<String>> releases = new ArrayList<List<String>>();
def list = ["7.5.9", "7.5.8", "7.5.7", "7.5.6", "7.5.5", "7.5.4", "7.5.3", "7.5.2", "7.5.1", "7.5.0", "6.5.1", "6.5.0"];

I want to have collection for every release First list of versions 1.0.0, 1.0.1, 1.0.2, Second list of versions 1.5.0, 1.5.1 Third list of versions 2.0.0 ... and so on for every release

0

4 Answers 4

3

Since the release versions have two digits, the input list may be grouped by the prefix (thus getting a map of String, List<String>) using Collectors.groupingBy and then the list of the versions is sorted using Collectors.collectingAndThen:

List<List<String>> versions = new ArrayList<>(
        list
            .stream()
            .collect(Collectors.groupingBy(
                str -> str.substring(0, str.lastIndexOf('.')),
                Collectors.collectingAndThen(
                    Collectors.toList(),
                    (List<String> lst) -> { lst.sort(String::compareTo); return lst; }
                )
            ))
            .values() // Collection<List<String>>
        );

versions.forEach(System.out::println);

Output:

[1.0.0, 1.0.1, 1.0.2]
[2.0.0]
[3.0.0, 3.0.1]
[1.5.0, 1.5.1]
[2.5.0]
[3.5.0]

The code above assumes the format of the release part in the version always has at least two dots (major and minor versions).

If some versions may not comply with the initial format (e.g., there are 0.1 or 1.0.2.1), the following grouping condition should work fine: str -> str.substring(0, str.indexOf('.', str.indexOf('.') + 1) + 1), - the release prefix is assumed to contain at least 1 dot . and at most two dots.


Example Groovy implementation:

def list = ["3.5.0", "3.0.1", "3.0.0", "2.5.0", "2.0.0", "1.5.1", "1.5.0", "1.0.2", "1.0.1", "1.0.0"]

def versions = new ArrayList<> (list.groupBy { 
    it.substring(0, it.lastIndexOf('.')) 
}.values())
.each { it.sort() }

versions.each {println it }

Output:

[3.5.0]
[3.0.0, 3.0.1]
[2.5.0]
[2.0.0]
[1.5.0, 1.5.1]
[1.0.0, 1.0.1, 1.0.2]

Update

The following Groovy code fixes sorting issues and also removes the highest version as well as the empty results:

def list = ["3.5.0", "3.0.1", "3.0.0", "2.5.0", "2.0.0", "1.5.1", "1.5.0", "1.0.1", "1.0.0", 
"1.0.10", "1.0.11", "1.0.2", "1.0.3", "1.0.4", "1.0.5", "1.0.6", "1.0.7", "1.0.8", "1.0.9"]

def versions = new ArrayList<> (
    list
        .sort() // sort initial list
        .groupBy {
            it.substring(0, it.lastIndexOf('.')) 
        }.values()
)
.each { it.sort{ a,b -> Integer.compare(
    Integer.parseInt(a.substring(a.lastIndexOf('.') + 1)), 
    Integer.parseInt(b.substring(b.lastIndexOf('.') + 1))
)}.removeAt(it.size() - 1) }

versions.removeIf { it.empty } // remove empty sublists if any found

versions.each {println it }

Output

[1.0.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6, 1.0.7, 1.0.8, 1.0.9, 1.0.10]
[1.5.0]
[3.0.0]
Sign up to request clarification or add additional context in comments.

10 Comments

do you know how to make this algorithm to work for groovy
do you how to sort it to be like [3.5.0] [3.0.1, 3.0.0] [2.5.0] [2.0.0] [1.5.1, 1.5.0] [1.0.2, 1.0.1, 1.0.0] and remove the hieghst version for every release, if it is only 1, remove it, expect [3.0.0] [1.5.0] [1.0.1, 1.0.0]
if there are more version, they are not sorted correctly, for example [1.0.0, 1.0.1, 1.0.10, 1.0.11, 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6, 1.0.7, 1.0.8, 1.0.9,
I fix the sort. Change "it.sort()" with "{ a,b -> a.compareToIgnoreCase b}"
@ivankolev, you may check this answer
|
2

Try this.

public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    list.add("3.5.0");
    list.add("3.0.1");
    list.add("3.0.0");
    list.add("2.5.0");
    list.add("2.0.0");
    list.add("1.5.1");
    list.add("1.5.0");
    list.add("1.0.2");
    list.add("1.0.1");
    list.add("1.0.0");

    Collections.sort(list);
    Map<String, List<String>> map = new TreeMap<>();
    for (String e : list)
        map.computeIfAbsent(e.replaceFirst("\\.\\d+$", ""), k -> new ArrayList<>()).add(e);
    List<List<String>> releases = new ArrayList<>(map.values());
    System.out.println(releases);
}

output:

[[1.0.0, 1.0.1, 1.0.2], [1.5.0, 1.5.1], [2.0.0], [2.5.0], [3.0.0, 3.0.1], [3.5.0]]

1 Comment

do you know how to make this algorithm to work for groovy
1

Use streams:

List<List<String>> versions =
    list.stream()
        .collect(Collectors.groupingBy(/* a function which extracts the version */))
        .values()  /* gives you a Collection<List<String>>, stop here if you don't need it as an actual List */
        .stream()
        .collect(Collectors.toList());

An example of "a function which extracts the version" for the values shown could be:

value -> value.substring(0, value.lastIndexOf('.'))

Comments

1

Down below is a pure idiomatic Groovy version w/o Java streams and other strange constructs:

def list = ["7.5.9", "7.5.8", "7.5.7", "7.5.6", "7.5.5", "7.5.4", "7.5.3", "7.5.2", "7.5.1", "7.5.0", "6.5.1", "6.5.0"]

def collector = {
    List asInts = it.split( /\./ )*.toInteger()
    [ sum:asInts.reverse().withIndex().collect{ v, ix -> 10.power( ix ) * v }.sum(), major:asInts[ 0 ], original:it ]
}

def listOfSublists = list.collect collector sort{ it.sum } groupBy{ it.major } values()*.collect{ it.original }

assert listOfSublists.toString() == '[[6.5.0, 6.5.1], [7.5.0, 7.5.1, 7.5.2, 7.5.3, 7.5.4, 7.5.5, 7.5.6, 7.5.7, 7.5.8, 7.5.9]]'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.