0

I came across this question in CodeWars recently & tried to solve it using Swift 5 (which I'm new to):

Given a string of digits, you should replace any digit below 5 with '0' and any digit 5 and above with '1'. Return the resulting string. Note: input will never be an empty string

I come from a Python background where we could using indexing with if statements to solve this particular problem like this:

def bin(x):
    newstr = ""
    for num in x:
        if int(num) < 5:
            newstr += "0"
        else:
            newstr += "1"
    return newstr

But when I tried to use indexing in Swift( like the Python style), I failed...which, after a while of researching made me come across this method: String.replacingOccurrences(of: , with: )

So if my Swift code for the above ques is like this:

func fakeBin(digits: String) -> String {
  
  for i in digits{
    
    if (Int(i)<5){
      some code to replace the char with '0'
    }
    else{some code to replace the char with '1'}
  
    return digits
  }

How do I use the above method String.replacingOccurrences(of: , with: ) in my code and achieve the desired output? If this is not possible, how else can we do it?

Note: I have already looked up for solutions on the website & found one:How do I check each individual digit within a string? But wasn't of any use to me as the questioner wanted the help in Java

2 Answers2

1

A Swift String is a collection of Characters. You can map each character to "0" or "1", and join the result to a new string:

func fakeBin(digits: String) -> String {
    return String(digits.map { $0 < "5" ? "0" : "1" })
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
0

Your code equivalent would be:

func fakeBinBasicForLoop(digits: String) -> String {
    var output = ""
    for aChar in digits {
        if let intValue = Int(String(aChar)) { //It's a number
            if intValue < 5 {
                output.append("0")
            } else {
                output.append("1")
            }
        } else { //Not a number
            output.append(aChar)
        }
    }
    return output
}

I'm checking if it's an integer, just in case.

Manually, with replacingOccurrences(of:with:):

func fakeBinReplacingOccurences(digits: String) -> String {
    var output = digits
    output = output.replacingOccurrences(of: "0", with: "0") //No really needed in this case, we can ommit it
    output = output.replacingOccurrences(of: "1", with: "0")
    output = output.replacingOccurrences(of: "2", with: "0")
    output = output.replacingOccurrences(of: "3", with: "0")
    output = output.replacingOccurrences(of: "4", with: "0")
    output = output.replacingOccurrences(of: "5", with: "1")
    output = output.replacingOccurrences(of: "6", with: "1")
    output = output.replacingOccurrences(of: "7", with: "1")
    output = output.replacingOccurrences(of: "8", with: "1")
    output = output.replacingOccurrences(of: "9", with: "1")
    return output
}

The issue is that it iterate all the string each time, so you'll have 9 loops. Allso, if you start by replacing 5, 6, 7, 8, 9 (ie in reverse order), your higher values will be replaced by 1, and then, replaced by 0. Order matters.

An alternative solution with reduce(into:_:):

func fakeBinReduceInto(digits: String) -> String {

    let output = digits.reduce(into: "") { partialResult, character in
        guard let intValue = Int(String(character)) else { partialResult.append(character); return }
        if intValue < 5 {
            partialResult.append("0")
        } else {
            partialResult.append("1")
        }
    }
    return output
}

You can also use a map() as suggested by other answers.

Larme
  • 24,190
  • 6
  • 51
  • 81
  • Might I suggest renaming `intValue` (which sounds like it could be an ASCI or unicode char code) to just `digit`? – Alexander Jun 20 '22 at 13:57
  • I would have named it `unicode` or `asciiValue`, but that's how I "name". Maybe `asInt` then? – Larme Jun 20 '22 at 13:58
  • Respectfully disagreeing: Neither part of `intValue` is useful: There's almost nothing in a program that *isn't* a "value" (even classes, functions and protocols can themselves be passed values), and the type information already communicates that's an "int". So the question is: "which integer is it"? and my proposed answer is: "it's a digit" – Alexander Jun 20 '22 at 14:09