Reputation: 53
So I am currently experimenting with Streams and I try to calculate the average of the numbers in the String "589 Hello 56" in a stream. My approach is like this:
List <int[]> experiment = a.stream()
.map(x -> x.replaceAll("[^0-9]", "").split("\\D+"))
.map(x-> Arrays.asList(x).stream().mapToInt(Integer::parseInt).toArray())
.collect(Collectors.toList());
So I first get a Stringarray with "589 56", because I split the String. But after that I try to convert everything to an Integerarray to get the average more easily and it doesn´t work, because the "589 56" converts to "58956". Does anyone have a better approach? Thanks in advance.
Upvotes: 3
Views: 811
Reputation: 60016
To calculate the average using stream, you need :
double average = Arrays.stream(a.split("\\D+")) // split with non degits ["589", "56"]
.mapToInt(Integer::valueOf) // convert each string to integer [589, 56]
.average() // OptionalDouble
.getAsDouble(); // double 322.5
Or if you are not sure that your string can contain any number, then you need to avoid this with :
.orElse(0);
or
.orElseThrow(() -> new IllegalArgumentException("no number in the string"));
instead of .getAsDouble();
Or if you want to go deeper and for example avoid cases where the numbers can be in front of any non digits for example a45 Hello 9a7
where the numbers can be a part of a word, in this case you can go with Pattern and Matcher with this regex \b\d+\b
, which use work boundary, like so :
double average = Pattern.compile("\\b\\d+\\b")
.matcher(a)
.results()
.map(MatchResult::group)
.mapToInt(Integer::valueOf)
.average()
.orElse(0);
This last solution can work only from Java9+.
Upvotes: 7
Reputation: 17299
Try this one
String s = "589 Hello 56";
OptionalDouble average = Arrays.stream(s.split("\\D+"))
.mapToInt(Integer::parseInt)// or maybe .mapToDouble(Double::parseDouble)
.average();
Upvotes: 1
Reputation: 1393
The call to replaceAll strips all non-numeric characters from the string including the spaces. This converts '589 Hello 56' into '58956'. Try using replaceAll("[^0-9\\s]", "")
.
You will also need to split on the separator characters (i.e., the spaces) instead of the digits.
Upvotes: 0