-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

BoB
  • 11
  • 3
  • 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! – GhostCat Oct 11 '21 at 08: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 https://stackoverflow.com/questions/30342744/swift-how-to-get-integer-from-string-and-convert-it-into-integer instead – Larme Oct 11 '21 at 08:55
  • Regarding this error check this : https://stackoverflow.com/a/57156631/14733292 And this will help you ```"1abc2x30yz67".components(separatedBy: CharacterSet.decimalDigits.inverted).compactMap({Int($0)}).reduce(0, +)``` – Raja Kishan Oct 11 '21 at 08: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? – BoB Oct 11 '21 at 09:06
  • Yes use while loop and tide another var for tracking nambar. Just iterate each character and find out while number until latter – Raja Kishan Oct 11 '21 at 09:14

2 Answers2

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)
Muhammad Nawaz
  • 1,113
  • 6
  • 15
  • Shouldn't this produce `1 + 2 + 3 + 0 + 6 + 7` and not `1 + 2 + 30 + 67`, outputting `19` instead of `100` – Larme Oct 11 '21 at 09:10
  • You should not be force unwrapping the return value of the fallible `Int` init, you should be optional binding the value instead. – Dávid Pásztor Oct 11 '21 at 09:11
  • @Larme no i just convert into integer and sum it let me think about it – Muhammad Nawaz Oct 11 '21 at 09:12
  • @DávidPásztor got you sir – Muhammad Nawaz Oct 11 '21 at 09:13
  • 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". – Larme Oct 11 '21 at 09:37
-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)")
Larme
  • 24,190
  • 6
  • 51
  • 81
  • 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? – Raja Kishan Oct 11 '21 at 10:00
  • 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. – Larme Oct 11 '21 at 10:03