Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find all combination of string array in swift

I have an Array of String and I want to find all the possible combinations of its element

For Example :

Array = [A,B,C,D]

should produce result as :

[A,AB,AC,AD,ABC,ABD,ACD,ABCD,B,BC,BD,BCD,C,CD,D]

Here is my Logic :

  var array = ["A", "B", "C","D"]
  var list = [String]()
  for i in 0..<array.count{
    let c = array[i]
    list.append(c)
    var d = c
    for count in 1..<array.count{

        if i+count < array.count{
            for j in i+count..<array.count{
                var a = d
                a.appendContentsOf(array[j])
                print("a : \(a)")
                list.append(a)
            }

        }
        d = c
        d.appendContentsOf(array[count])
        print("d : \(d)")
    }
}
print(list.description)

Its Output is :

["A", "AB", "AC", "AD", "ABC", "ABD", "ACD", "B", "BC", "BD", "BBD", "C", "CD", "D"]

This output is missing ABCD and wrongly printed BCD as BBD

Anyone Please Help me in this by Enhancing my code or suggesting your own logic for this.

like image 940
Preeti Rani Avatar asked Nov 02 '25 03:11

Preeti Rani


1 Answers

@yannick's answer is very close.

By computing a Power Set of your set, you obtain all the possible subsets (including your original set and the empty set).

Once you have obtained the Power Set, all you have to do is join the subsets into a single string in order to obtain the result that you're looking for.

Here's the complete solution (along with updated code and plenty of comments):

extension Array {
    var powerset: [[Element]] {
        guard count > 0 else {
            return [[]]
        }

        // tail contains the whole array BUT the first element
        let tail = Array(self[1..<endIndex])

        // head contains only the first element
        let head = self[0]

        // computing the tail's powerset
        let withoutHead = tail.powerset

        // mergin the head with the tail's powerset
        let withHead = withoutHead.map { $0 + [head] }

        // returning the tail's powerset and the just computed withHead array
        return withHead + withoutHead
    }
}

let myArray = ["A", "B", "C", "D"]
print(myArray.powerset) // -> [["D", "C", "B", "A"], ["C", "B", "A"], ["D", "B", "A"], ["B", "A"], ["D", "C", "A"], ["C", "A"], ["D", "A"], ["A"], ["D", "C", "B"], ["C", "B"], ["D", "B"], ["B"], ["D", "C"], ["C"], ["D"], []]

// joining the subsets
let myResult = myArray.powerset.map { $0.sort().joinWithSeparator("") }
print(myResult) // -> ["A", "AB", "ABC", "ABCD", "ABD", "AC", "ACD", "AD", "B", "BC", "BCD", "BD", "C", "CD", "D", ""]

PS

Note that this solution uses a recursive approach, while yours was using an iterative approach.

PPS

If you don't want the empty string "" in your solution, you can just filter it away:

let myResult = myArray.powerset.map({ $0.sort().joinWithSeparator("") }).filter({ $0 != "" })

print(myResult) // -> ["A", "AB", "ABC", "ABCD", "ABD", "AC", "ACD", "AD", "B", "BC", "BCD", "BD", "C", "CD", "D"]
like image 132
Federico Zanetello Avatar answered Nov 03 '25 19:11

Federico Zanetello



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!