Reputation: 25
I was recently asked to write a function in java which will sum the numbers(not digits) in a string. e.g. if the string is abc35zz400tt15, the output should be 450.
this is what i wrote :
public static void getSum(String a){
String[] arr=a.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
int sum=0;
for(int i=0;i<arr.length;i++){
if(Pattern.matches("[0-9]+", arr[i]))
sum+=Integer.parseInt(arr[i]);
}
System.out.println(sum);
}
Is there a more efficient way to do this as they didn't look satisfied with the above code.
Upvotes: 2
Views: 833
Reputation: 133609
If you are look forward efficiency regex matching and object allocations could be overkill for the task. You can scan the string backwards and accumulate the number:
int currentPower = 1;
int length = string.length();
int value = 0;
for (int i = string.length()-1; i >= 0; --i) {
char curChar = string.charAt(i);
if (curChar >= '0' && curChar <= '9') {
value += (curChar - '0') * currentPower;
currentPower *= 10;
}
else
currentPower = 1;
}
Upvotes: 5
Reputation: 46435
Alternative solution: replace everything that is not a number with a +
sign, and evaluate the result. That is not very efficient in Java, but there are other instances (bash
for example) where it would be the right thing to do. So I'm putting that suggestion here "for future visitors".
Clarification: I mean something like
echo abc35zz400tt15 | sed -E 's/[^0-9]+/\+/g' | sed 's/^\+//' | bc
That is
find one or more characters that are not a digit
replace all of them with a +
then strip the first `+` if it's the first character in the line
and evaluate the result
The above yields
450
as expected.
Note - bc
doesn't like it when the string you feed it starts with a +
- hence the need for the second sed
.
Note 2 - the -E
flag is used on Mac OSX to set "extended regular expressions". This gives special meaning ('one or more') to the +
character - shorter than \{1,}\}
... I know the Mac one is subtly different than the gnu
one, but don't know whether this is one of those occasions.
Upvotes: 1
Reputation: 333
Edit:: Whoops, read too fast, you wanted numbers, not digits. I believe someone has already answered above. I also have answered the question using my original (but incorrect) approach
Previous Answer
Look at Java's isDigit(char c)
. It may look something like:
public static void getSum(string a) {
int sum = 0;
for(int i = 0; i < a.length(); i++) {
if(Character.isDigit(a.charAt(i))) {
sum += Integer.parseInt(a.charAt(i));
}
}
System.out.println(sum);
}
New answer using an iterative approach
public static void getSum(String a) {
int sum = 0;
String num = "";
for(int i = 0; i < a.length(); i++) {
if(Character.isDigit(a.charAt(i))) {
num = num + a.charAt(i);
} else {
if(!num.equals("")) {
sum = sum + Integer.parseInt(num);
num = "";
}
}
}
if(!num.equals("")) {
sum = sum + Integer.parseInt(num);
}
System.out.println(sum);
}
Upvotes: -2
Reputation: 328775
If you fancy Java 8, you can write it in a fairly expressive way:
int sum = Arrays.stream(input.split("\\D+"))
.filter(s -> ! s.isEmpty())
.mapToInt(Integer::parseInt)
.sum();
Upvotes: 1
Reputation: 195
Quick solution, without any usage of Matcher and Pattern:
String line = "abc35zz400tt15";
int sum = 0;
String[] numbers = line.split("\\D");
for (String digit : numbers) {
if (digit.length() > 0) sum += Integer.valueOf(digit);
}
Upvotes: 2
Reputation: 81124
I think it would be a bit simpler just to search for the pattern one at a time, rather than split the String.
Pattern pattern = Pattern.compile("[0-9]+"); //or you can use \\d if you want
Matcher matcher = pattern.matcher(a);
while(matcher.find()) {
sum += Integer.parseInt(matcher.group());
}
Upvotes: 6