Home > Software design >  Swift Algorithm : how to get String that includes all substrings without repetition
Swift Algorithm : how to get String that includes all substrings without repetition

Time:04-07

Suppose you get an input like below:

hello helloSwift Swi Apple le

(total 5)

I want a function to receive the above inputs and return a String "helloSwiftApple". The returning String must "include" all input Strings without repetitions. For instance, the returning String can't be "hellohelloSwiftSwiApplele" How can I do this with Swift?

Thanks in advance and sorry for my bad explanation. Just got started studying algorithm using Swift.

CodePudding user response:

This is a bit of a "brute force" approach, but it may work for you.

  • split the string into an array a of unique "words"
  • loop through the array for i in 0..<a.count
    • remove element i word
    • does any element in a contain word?
    • if NO
      • add word to new array
    • put word back in a
  • return a joined into string

So, we can use this extension to remove duplicates from an array (Hacking with Swift):

extension Array where Element: Hashable {
    func removingDuplicates() -> [Element] {
        var addedDict = [Element: Bool]()
        
        return filter {
            addedDict.updateValue(true, forKey: $0) == nil
        }
    }
    
    mutating func removeDuplicates() {
        self = self.removingDuplicates()
    }
}

and we can write a func like this:

func parseString(_ str: String) -> String {
    
    // split the string into an array of "words" (no spaces)
    var a1: [String] = str.components(separatedBy: " ").removingDuplicates()
    
    // an array to hold the unique words
    var a2: [String] = []
    
    // for each word
    for i in 0..<a1.count {
        // remove the word from the array
        let word = a1.remove(at: i)
        // filter the remaining array by elements containing word
        let n = a1.filter { $0.contains(word) }
        // if no elements contain word
        if n.count == 0 {
            // append it to array of unique words
            a2.append(word)
        }
        // put the word back into the full array
        a1.insert(word, at: i)
    }
    
    // change "-" to "" for no separators
    return a2.joined(separator: "-")
}

A quick test like this:

    let test: [String] = [
        "1 hello helloSwift Swi Apple le",
        "2 I want a string",
        "3 i want a string",
        "4 I want a function to receive the above inputs and return a String",
        "5 i want a function to receive the above inputs and return a String",
        "6 abc aBc Abc abc ABC aabc",
        "7 droid android otherdroid and android and otherdroid",
    ]

    test.forEach { s in
        let rs = parseString(s)
        print("Orig:", s)
        print("Ret :", rs)
        print()
    }

outputs this to the debug console:

Orig: 1 hello helloSwift Swi Apple le
Ret : 1-helloSwift-Apple

Orig: 2 I want a string
Ret : 2-I-want-string

Orig: 3 i want a string
Ret : 3-want-string

Orig: 4 I want a function to receive the above inputs and return a String
Ret : 4-I-want-function-to-receive-the-above-inputs-and-return-String

Orig: 5 i want a function to receive the above inputs and return a String
Ret : 5-want-function-to-receive-the-above-inputs-and-return-String

Orig: 6 abc aBc Abc abc ABC aabc
Ret : 6-aBc-Abc-ABC-aabc

Orig: 7 droid android otherdroid and android and otherdroid
Ret : 7-android-otherdroid

As you'll immediately notice, you didn't mention case-sensitivity, so we haven't addressed that... that's why examples 2 & 3 and 4 & 5 return different results:

  • "I" is not found in "string"
  • "i" is found in "string"
  • Related