1

I have an array of string and another string:

let array = ["one","two","three"]
let string = "one two three four five six seven"

What is a Swifty way of removing occurrences found in the array from the string? I tried a for loop, but wanted to see if filter would work in such a case?

2
  • 3
    If you remove the occurrences what's going to happen with the whitespace characters? Commented Mar 19, 2019 at 19:42
  • stackoverflow.com/questions/48395980/… Commented Mar 19, 2019 at 19:42

4 Answers 4

5

I believe the kind of filter expression you're thinking of is this:

let finalString = string
    .split(separator: " ")  // Split them
    .lazy                   // Maybe it's very long, and we don't want intermediates
    .map(String.init)       // Convert to the same type as array
    .filter { !array.contains($0) } // Filter
    .joined(separator: " ") // Put them back together
Sign up to request clarification or add additional context in comments.

2 Comments

You could get rid of the .map if you just did !array.contains(String($0).
@LinusGeffarth I did that originally, and edited to use the map. It think the map is more beautiful and explicit, when combined with lazy. But I agree, they're very similar, and it's more a matter of style than substance.
3

In Swift 4.2 there is a removeAll(where: API.

let array = ["one","two","three"]
let string = "one two three four five six seven"

var components = string.components(separatedBy: " ")
components.removeAll{array.contains($0)}
let result = components.joined(separator: " ") // "four five six seven"

Comments

2

Efficient solution

The following is an efficient solution that replaces the occurrence of an element in array, plus its surrounding spaces, with one space only:

let array = ["one","two","three"]
let str = "  eight one  four two   three five   six seven "
var result = ""

var i = str.startIndex

while i < str.endIndex {
    var j = i
    while j < str.endIndex, str[j] == " " {
        j = str.index(after: j)
    }
    var tempo1 = ""
    if i != j { tempo1 += str[i..<j] }

    if j < str.endIndex { i = j } else {
        result += tempo1
        break
    }

    while j < str.endIndex, str[j] != " " {
        j = str.index(after: j)
    }

    let tempo2 = String(str[i..<j])

    if !array.contains(tempo2) {
        result += tempo1 + tempo2
    }

    i = j
}

print(result)  //␣␣eight␣four␣five␣␣␣six␣seven␣

The symbol represents a space.


Benchmarks

Try it online!

Vadian's      : 0.000336s
JP Aquino's   : 0.000157s
Rob Napier's  : 0.000147s
This Solution : 0.000028s

This is at least 5 times faster than any other solution.


Leaving spaces intact

If you don't want to remove spaces (since they're not part of the original array), then this will do:

let array = ["one","two","three"]
let str = "one two three four five six seven "
var result = ""

var i = str.startIndex

while i < str.endIndex {
    var j = i
    while j < str.endIndex, str[j] == " " {
        j = str.index(after: j)
    }

    if i != j { result += str[i..<j] }
    if j < str.endIndex { i = j } else { break }

    while j < str.endIndex, str[j] != " " {
        j = str.index(after: j)
    }

    let tempo = String(str[i..<j])

    if !array.contains(tempo) {
        result += tempo
    }

    i = j
}

print(result)   //␣␣␣four five six seven␣

Comments

1
let array = ["one","two","three"]
let string = "one two three four five six seven"

//Convert string to array
var stringArray  = string.components(separatedBy: " ")

//Remove elements from original array
stringArray = stringArray.filter { !array.contains($0) }

//Convert stringArray back to string
let finalString = stringArray.joined(separator: " ")
print(finalString)// prints "four five six seven"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.