In your output example, it was not entirely clear what you really want:
all combinations and their permutations:
["AB", "BA", "AC", "CA", "AD", "DA", ..., "ABCD", "ABDC", "ACBD", "ACDB", ...]
just all the combinations:
["AB", "AC", "AD", "BC", "BD", "CD", "ABC", "ABD", ...]
I can recommend @oisdk a large Swift library: SwiftSequence for them, it has many useful features. In the Combinations section, he even shows an example of its use with the Power Set , which you almost certainly look for in case 1. When importing files from his library, you can create the powerSet function on CollectionType as follows:
extension CollectionType { func powerSet() -> LazySequence<FlattenSequence<LazyMapSequence<Self, ComboSeq<Self.Generator.Element>>>>{ var i = 0 return lazy.flatMap{ _ in self.lazyCombos(++i) } } }
This method is evaluated lazily, which means that it is only evaluated when it really needs to. Now you have mentioned that you only want to have combinations of at least two elements. This is easily done using the filter method:
let combinations = ["A", "B", "C", "D"].powerSet().filter{ $0.count >= 2 } // As an array: [["A", "B"], ["A", "C"], ["A", "D"], ["B", "C"], ["B", "D"], ["C", "D"], ["A", "B", "C"], ["A", "B", "D"], ["A", "C", "D"], ["B", "C", "D"], ["A", "B", "C", "D"]]
In case 2., where you also need permutations, you can do this:
let combPerms = combinations.flatMap{ $0.permutations() } // As an array: [["A", "B"], ["B", "A"], ["A", "C"], ["C", "A"], ["A", "D"], ["D", "A"], ["B", "C"], ["C", "B"], ["B", "D"], ["D", "B"], ["C", "D"], ["D", "C"], ["A", "B", "C"], ["A", "C", "B"], ["B", "A", "C"], ["B", "C", "A"], ["C", "A", "B"], ["C", "B", "A"], ["A", "B", "D"], ["A", "D", "B"], ["B", "A", "D"], ["B", "D", "A"], ["D", "A", "B"], ["D", "B", "A"], ["A", "C", "D"], ["A", "D", "C"], ["C", "A", "D"], ["C", "D", "A"], ["D", "A", "C"], ["D", "C", "A"], ["B", "C", "D"], ["B", "D", "C"], ["C", "B", "D"], ["C", "D", "B"], ["D", "B", "C"], ["D", "C", "B"], ["A", "B", "C", "D"], ["A", "B", "D", "C"], ["A", "C", "B", "D"], ["A", "C", "D", "B"], ["A", "D", "B", "C"], ["A", "D", "C", "B"], ["B", "A", "C", "D"], ["B", "A", "D", "C"], ["B", "C", "A", "D"], ["B", "C", "D", "A"], ["B", "D", "A", "C"], ["B", "D", "C", "A"], ["C", "A", "B", "D"], ["C", "A", "D", "B"], ["C", "B", "A", "D"], ["C", "B", "D", "A"], ["C", "D", "A", "B"], ["C", "D", "B", "A"], ["D", "A", "B", "C"], ["D", "A", "C", "B"], ["D", "B", "A", "C"], ["D", "B", "C", "A"], ["D", "C", "A", "B"], ["D", "C", "B", "A"]]
You can convert them to Set from String or Array :
let array = Array(combPerms) let set = Set(combPerms)
But I highly recommend using the lazy version;) And yes, to remove duplicates, you can just use Set(["A", "B", "C", "D"]) instead of just ["A", "B", "C", "D"]
You can also make case 2. in one move as follows:
let x = ["A", "B", "C", "D"] let result = Set( x.indices .flatMap{ x.lazyCombos($0 + 1) } .filter{ $0.count >= 2 } .flatMap{ $0.permutations() } .map{ $0.joinWithSeparator("") })