Replace multiple words from a String based on the

2020-05-01 08:41发布

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?

标签: swift string
4条回答
爷、活的狠高调
2楼-- · 2020-05-01 09:07

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␣
查看更多
小情绪 Triste *
3楼-- · 2020-05-01 09:11

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"
查看更多
▲ chillily
4楼-- · 2020-05-01 09:25

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
查看更多
Bombasti
5楼-- · 2020-05-01 09:26
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"
查看更多
登录 后发表回答