I have a list of Strings such as "/100" "/100/200"
.
I wish to split these strings by /
, and would then get a List of List of Integers such as [[100],[100,200]]
.
I want to traverse this list of list and get nth element from each list if that list is long enough, else move to the next list.
It is known that each inner list would be maximum of length n
.
Example :
n= 3
slashString -> "/100/200/300","/200/300","/100/200/400"
In the above case I want a List of Integers as 300,400
.
List<Integer> output = slashString.stream()
.map(x->Arrays.stream(x.split("/")).collect(Collectors.toList()))
.filter(x->x.size()==3)
I am able to think till above. How would I eventually collect the 3rd element across all the list of integers.
You are almost there.
After filtering list of size 3, get the third element and convert it to an Integer.
Also, note that splitting a String /100/200
will give you a String[]
(["", "100", "200"]
) with an empty string as the first element. So, I have skipped the first element using skip(1)
List<Integer> result = slashString.stream()
.map(x-> Arrays.stream(x.split("/"))
.skip(1)
.collect(Collectors.toList()))
.filter(x -> x.size() >= 3)
.map(list -> Integer.valueOf(list.get(2)))
.collect(Collectors.toList());
Just map each List
to the 3rd element of the List
and collect:
List<Integer> list = Stream.of ("100/200/300","200/300","100/200/400")
.map(x->Arrays.stream(x.split("/")).collect(Collectors.toList()))
.filter(x->x.size()==3)
.map(l->Integer.valueOf (l.get(2)))
.collect(Collectors.toList());
Note that you have to eliminate the leading /
of the input String
s. Otherwise the lengths of the 1st and 3rd List
s will be 4, and they won't pass the filter. Or you can require the List
size to be 4 instead of 3 (and change l.get(2)
to l.get(3)
).
Remove all but the third term using regex, filter out empties, voila!
List<Integer> list = Stream.of("100/200/300", "200/300", "100/200/400")
.map(s -> s.replaceAll("^([^/]/[^/]/)?([^/]+)?(/.*)?", "$2"))
.filter(s -> !s.isEmpty())
.map(Integer::valueOf)
.collect(Collectors.toList());
The regex always matches the whole string, and replaces it with the 3rd term, which was captured as group 2, but because everything is optional, group 2 (the final result) is blank if there isn’t a 3rd term.
This approach only ever deals with Strings, which keeps things simpler by avoiding ugly array code.
You do not need to make intermediate lists. Instead turn each string into a stream that's either empty or contains just the nth element with skip(n).limit(1)
and use flatMap
to merge all the little streams together:
Pattern delimiter = Pattern.compile("/");
int n = 3;
List<Integer> result = slashString.stream()
.flatMap(s -> delimiter.splitAsStream(s).skip(n).limit(1))
.map(Integer::valueOf)
.collect(toList());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With