-1
var numsInStr = "1abc2x30yz67"
var sum = 0
for i in numsInStr {
    if i.isNumber == true {
       sum += i
    }
}
print(sum)
  • Problem is in if statemt to summing numbers. And it returns - "Cannot convert value of type 'String.Element' (aka 'Character') to expected argument type 'Int'"
  • It is possible to solve this problem like mine. I saw some answers but answers are very short and misunderstanding

Input: 1abc2x30yz67 Output: 100

5
  • And note: your assignment seems to be: iterate a random string, and sum all the digits within in it. Programming requires to be really precise about all details! Commented Oct 11, 2021 at 8:39
  • If you code worked, currently, outtput should be 6, you are counting the number of occurences of numbers, since you are doing "+i". You aren't converting it to numbers. Also, since you are doing an iteration character by character, else, even if converting into its integer, then your logic is 1 + 2 + 3 + 0 + 6 + 7, not 1 + 2 + 30 + 67. So your logic seems flawed... You might want to look for stackoverflow.com/questions/30342744/… instead Commented Oct 11, 2021 at 8:55
  • Regarding this error check this : stackoverflow.com/a/57156631/14733292 And this will help you "1abc2x30yz67".components(separatedBy: CharacterSet.decimalDigits.inverted).compactMap({Int($0)}).reduce(0, +) Commented Oct 11, 2021 at 8:59
  • @RajaKishan Yes I saw that code before but this code is misunderstanding for beginners. Is it possible to solve this problem with loop or something? Commented Oct 11, 2021 at 9:06
  • Yes use while loop and tide another var for tracking nambar. Just iterate each character and find out while number until latter Commented Oct 11, 2021 at 9:14

2 Answers 2

2

your solution is not working because you are adding character type in to integrate type value, first you need to convert your character object into string then convert into integer for sum. hope this may helps you thanks 😊

    var numsInStr = "1abc2x30yz67"
    var sum = 0

    for i in numsInStr 
    {
        if i.isNumber == true 
        {
            sum = sum + Int(String(i))
        }
   }

   print(sum)

for sum of all number from your String following is the best solution you will get the sum of 100 as you required in your question.

let numsInStr = "1abc2x30yz67"
    .components(separatedBy: .letters)
    .compactMap(Int.init)
    .reduce(0, +)
print(numsInStr)
Sign up to request clarification or add additional context in comments.

5 Comments

Shouldn't this produce 1 + 2 + 3 + 0 + 6 + 7 and not 1 + 2 + 30 + 67, outputting 19 instead of 100
You should not be force unwrapping the return value of the fallible Int init, you should be optional binding the value instead.
@Larme no i just convert into integer and sum it let me think about it
@DávidPásztor got you sir
Since your two codes aren't equivalent, that's misleading. Your might want to explicitly tell that's they aren't. You are explaining why it's not compiling in the first part, and provide a higher level solution for the aim problem. Two different "fixes".
-1

What's the issue in sum += i, as the error said, i is a Character, and sum a Int.
Can you make addition between bananas & apples? It's the same logic here.
So you might want to have its Int equivalent with Int(i)

It's returning an optional value, because there is no guarantee that i is valid. You check isNumber before hand, but the line itself doesn't know that. So you can soft unwrap, or if you are sure force unwrap:

sum += Int(String(i))! //Char -> String -> Int

Because there is a String.init(someChar), and Int.init(someString), but not Int.init(someChar), that's why there is the double init().

BUT, keeping your logic, you are iterating characters per characters... So, in the end you have:

1 + 2 + 3 + 0 + 6 + 7 (ie 19), not 1 + 2 + 30 + 67 (ie 100) as expected.

So if you want to iterate, you need to "group" the consecutive numbers...

With basic for loops, your can do this (it's a possible solution, might no be the better one, but a working one)

let numsInStr = "1abc2x30yz67"

var lastWasNumber = false
var intStrings: [String] = []

for aCharacter in numsInStr {
    if aCharacter.isNumber {
        if !lastWasNumber {
            intStrings.append(String(aCharacter))
        } else {
            intStrings[intStrings.count - 1] = intStrings[intStrings.count - 1] + String(aCharacter)
        }
        lastWasNumber = true
    } else {
        lastWasNumber = false
    }
    print("After processing: \(aCharacter) - got: \(intStrings)")
}

print(intStrings)

var sum = 0
for anIntString in intStrings {
    sum += Int(anIntString)!
}
print("Sum: \(sum)")

At your level, never hesitate to add print() (but never just the variable, always add an additional text which will be context to know from where it's called).

The output being:

$>After processing: 1 - got: ["1"]
$>After processing: a - got: ["1"]
$>After processing: b - got: ["1"]
$>After processing: c - got: ["1"]
$>After processing: 2 - got: ["1", "2"]
$>After processing: x - got: ["1", "2"]
$>After processing: 3 - got: ["1", "2", "3"]
$>After processing: 0 - got: ["1", "2", "30"]
$>After processing: y - got: ["1", "2", "30"]
$>After processing: z - got: ["1", "2", "30"]
$>After processing: 6 - got: ["1", "2", "30", "6"]
$>After processing: 7 - got: ["1", "2", "30", "67"]
$>["1", "2", "30", "67"]
$>100

We rely on Int(someString) (and force unwrapping), but sum += Int(anIntString) ?? 0 should be safer. Since for too big values, if you have "a1234567890123456789123456789123456789" for instance, I'm not sure that Int will be big enough to handle that value. That some edges cases that you need to be aware of.

With high level methods, you can use componentsSeparated(by:) to get an array of only string & only letters. Then, you can filter() (if needed), or compactMap() and transform to Int if possible, then sum (with reduce(into:_:).

As suggested, another solution without keeping a list of String could be:

var sum = 0
var lastWasNumber = false
var currentIntString = ""

for aCharacter in numsInStr {
    if aCharacter.isNumber {
        if !lastWasNumber {
            sum += Int(currentIntString) ?? 0
            currentIntString = "" // Reset, but in fact since we override with the next line, it's not necessary to write it
            currentIntString = String(aCharacter)
        } else {
            currentIntString += String(aCharacter)
        }
        lastWasNumber = true
    } else {
        lastWasNumber = false
    }
    print("After processing: \(aCharacter) - got: \(currentIntString) - current sum: \(sum)")
}

sum += Int(currentIntString) ?? 0

print("Sum: \(sum)")

Here, we keep currentInString as a "buffer".

This could be simplified too by removing lastWasNumber and checking instead currentIntString:

var sum = 0
var currentIntString = ""

for aCharacter in numsInStr {
    if aCharacter.isNumber {
        if currentIntString.isEmpty {
            currentIntString = String(aCharacter)
        } else {
            currentIntString += String(aCharacter)
        }
    } else {
        sum += Int(currentIntString) ?? 0
        currentIntString = ""
    }
    print("After processing: \(aCharacter) - got: \(currentIntString) - current sum: \(sum)")
}

sum += Int(currentIntString) ?? 0

print("Sum: \(sum)")

2 Comments

You can directly calculate the sum without storing it in an array and without an extra loop for the sum array. It will reduce the time and space complexity. But maybe it's for an explanation?
Indeed. Instead of a [String], we could use a String to hold the current string (to know for instance, if we want to add a "7" or "67" in the sample). In the "else", we could add it, and "reset" that String, and add it at the end of the loop in case. But I think it would be maybe too much complex according to the user level.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.