在swift中找到字符串数组的所有组合

时间:2016-08-26 07:20:29

标签: arrays swift logic combinations

我有一个String数组,我想找到其元素的所有可能组合

  

例如:

     

数组= [A,B,C,D]

     

应该产生结果:

     

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

这是我的逻辑:

  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)
  

其输出是:

     

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

此输出缺少ABCD并错误地将BCD打印为BBD

任何人都可以通过增强我的代码或建议你自己的逻辑来帮助我。

5 个答案:

答案 0 :(得分:4)

@yannick 的答案非常接近。

通过计算集合的 Power Set ,您可以获得所有可能的子集(包括原始集和空集)。

获得Power Set后,您所要做的就是将子集连接成一个字符串,以获得您正在寻找的结果。

以下是完整的解决方案(以及更新的代码和大量评论):

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

请注意,此解决方案使用递归方法,而您的解决方案使用迭代方法。

PPS

如果您不想在解决方案中使用空字符串"",则可以将其过滤掉:

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"]

答案 1 :(得分:2)

看起来你想拥有数组的Power set

  

在数学中,任何集合S的幂集(或幂集)都是集合   S的所有子集,包括空集和S本身。

我在GitHub上找到了此代码。

extension Array {
    var powerset: [[Element]] {
        if count == 0 {
            return [self]
        }
        else {
            let tail = Array(self[1..<endIndex])
            let head = self[0]

            let withoutHead = tail.powerset
            let withHead = withoutHead.map { $0 + [head] }

            return withHead + withoutHead
        }
    }
}

println([1,2,3,4].powerset) -> [[4, 3, 2, 1], [3, 2, 1], [4, 2, 1], [2, 1], [4, 3, 1], [3, 1], [4, 1], [1], [4, 3, 2], [3, 2], [4, 2], [2], [4, 3], [3], [4], []]

答案 2 :(得分:0)

我找到了一个更简洁的答案。Power set of Collection.

原理是对集合的大小使用归纳法,如该链接所示。 这是该链接的代码副本。并全部归功于其作者。

extension Collection {
  public var powerSet: [[Element]] {
    guard let fisrt = self.first else {return [[]]}
    return self.dropFirst().powerSet.flatMap{[$0, [fisrt] + $0]}
  }
}
let s: Set<Int> = [1,2,3]
s.powerSet //[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
let a: Array<Int> = [1,2,3]
a.powerSet //[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]

答案 3 :(得分:0)

我知道已经给出了一些很好的答案,但是出于Java的背景,我只是想使用按位运算符(令人惊讶的是,在Swift中仍然可以使用这些运算符)放弃一些见识。

您可以尝试一下:

let len = stringArr.count

for i in 0 ..< (1<<len){
    print("{", terminator: "")

    for j in 0 ..< len {
        if ((i & (1<<j)) > 0) {
            print(stringArr[j], terminator: "")
        }
    }

    print("}")
}

您可以找到有关按位运算符here

的更多信息

答案 4 :(得分:0)

我还将使用此logic作为参考来拍摄照片:

extension RangeReplaceableCollection {
    var subSets : [SubSequence] {
        guard !isEmpty else { return [] }
        let count = self.count
        let n = 1 << count - 1
        var subSequences: [SubSequence] = .init(repeating: SubSequence(), count: n-1)
        (0 ..< n).map {
            var counter = 0
            for element in self {
                if $0 & 1 << counter > 0 {
                    subSequences[$0-1].append(element)
                }
                counter += 1
            }
        }
        return subSequences + [self[...]]
    }
}

游乐场测试:

["A", "B", "C","D"].subSets  // [["A"], ["B"], ["A", "B"], ["C"], ["A", "C"], ["B", "C"], ["A", "B", "C"], ["D"], ["A", "D"], ["B", "D"], ["A", "B", "D"], ["C", "D"], ["A", "C", "D"], ["B", "C", "D"], ["A", "B", "C", "D"]]

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