曾经绞尽脑汁,似乎无法提出一个优雅的解决方案。想知道是否有人可以帮助我。
我有一台Swift字典,每个键都有一个值数组,就像这样...
[A:[1, 2, 3], B:[4, 5, 6], C:[7, 8, 9]]
我需要将其转换成带有值的每种组合的字典数组...
[
[A:1, B:4, C:7],
[A:1, B:4, C:8],
[A:1, B:4, C:9],
[A:1, B:5, C:7],
[A:1, B:5, C:8],
[A:1, B:5, C:9],
[A:1, B:6, C:7],
[A:1, B:6, C:8],
[A:1, B:6, C:9],
[A:2, B:4, C:7],
[A:2, B:4, C:8],
[A:2, B:4, C:9],
[A:2, B:5, C:7],
[A:2, B:5, C:8],
[A:2, B:5, C:9],
[A:2, B:6, C:7],
...
[A:3, B:6, C:9],
]
答案 0 :(得分:0)
这是一种递归解决方案,它适用于原始字典中任意数量的键/数组对以及values数组中任意数量的值:
let dict = ["A":[1, 2, 3], "B":[4, 5, 6], "C":[7, 8, 9]]
func combine(source: [String : [Int]], partials: [[String : Int]] = [], final: inout [[String : Int]]) {
if source.isEmpty {
// base step of recursion
// there are no more (k:v) pairs in source, so add all of the partials (now final)
// to the final array
final.append(contentsOf: partials)
} else {
// source has a (k:v) pair, so take the first one
let (k, vals) = source.first!
var newsource = source
// remove key from newsource
newsource[k] = nil
// for each value in the key
for val in vals {
// add (k:v) to each partial dictionary
var newpartials = partials
// If new partials array is empty
if newpartials.isEmpty {
// create the array with the first [k:v]
newpartials = [[k : val]]
} else {
// otherwise, add [k:v] to each of the partial dictionaries
for pidx in newpartials.indices {
newpartials[pidx][k] = val
}
}
// recursive call to process the next value in source
combine(source: newsource, partials: newpartials, final: &final)
}
}
}
var result = [[String : Int]]()
combine(source: dict, final: &result)
print(result)
print(result.count)
[[“ A”:1,“ B”:4,“ C”:7],[“ A”:2,“ B”:4,“ C”:7],[“ A”:3 ,“ B”:4,“ C”:7],[“ C”:7,“ B”:5,“ A”:1],[“ C”:7,“ B”:5,“ A” :2],[“ C”:7,“ B”:5,“ A”:3],[“ C”:7,“ B”:6,“ A”:1],[“ C”:7 ,“ B”:6,“ A”:2],[“ C”:7,“ B”:6,“ A”:3],[“ C”:8,“ B”:4,“ A” :1],[“ C”:8,“ B”:4,“ A”:2],[“ C”:8,“ B”:4,“ A”:3],[“ C”:8 ,“ B”:5,“ A”:1],[“ C”:8,“ B”:5,“ A”:2],[“ C”:8,“ B”:5,“ A” :3],[“ B”:6,“ C”:8,“ A”:1],[“ B”:6,“ C”:8,“ A”:2],[“ B”:6 ,“ C”:8,“ A”:3],[“ A”:1,“ C”:9,“ B”:4],[“ A”:2,“ C”:9,“ B” :4],[“ A”:3,“ C”:9,“ B”:4],[“ B”:5,“ A”:1,“ C”:9],[“ B”:5 ,“ A”:2,“ C”:9],[“ B”:5,“ A”:3,“ C”:9],[“ B”:6,“ A”:1,“ C” :9],[“ B”:6,“ A”:2,“ C”:9],[“ B”:6,“ A”:3,“ C”:9]]
27
没有理由将其限制为String
和Int
。密钥应为符合Hashable
的任何类型。
要使函数通用,请将签名更改为:
func combine<KEY, VALUE>(source: [KEY : [VALUE]], partials: [[KEY : VALUE]] = [],
final: inout [[KEY : VALUE]]) where KEY: Hashable {
Dictionary
extension
@LeoDabus将此答案扩展为extension
上的Dictionary
,其中Value
是Collection
(谢谢Leo!):
extension Dictionary where Value: Collection {
func permutations() -> [[Key: Value.Element]] {
guard !isEmpty else { return [] }
var permutations: [[Key: Value.Element]] = []
permutate(&permutations)
return permutations
}
private func permutate(_ permutations: inout [[Key: Value.Element]], _ dictionaries: [[Key: Value.Element]] = []) {
if let (key, value) = first {
var dictionary = self
dictionary[key] = nil
for element in value {
var dictionaries = dictionaries
if dictionaries.isEmpty {
dictionaries += CollectionOfOne([key: element])
} else {
for index in dictionaries.indices {
dictionaries[index][key] = element
}
}
dictionary.permutate(&permutations, dictionaries)
}
} else {
permutations += dictionaries
}
}
}
let dict = ["A":[1, 2, 3], "B":[4, 5, 6], "C":[7, 8, 9]]
let result = dict.permutations()
print(result)
print(result.count)
[[“ B”:4,“ A”:1,“ C”:7],[“ B”:4,“ A”:2,“ C”:7],[“ B”:4 ,“ A”:3,“ C”:7],[“ A”:1,“ B”:4,“ C”:8],[“ A”:2,“ B”:4,“ C” :8],[“ A”:3,“ B”:4,“ C”:8],[“ A”:1,“ B”:4,“ C”:9],[“ A”:2 ,“ B”:4,“ C”:9],[“ A”:3,“ B”:4,“ C”:9],[“ C”:7,“ A”:1,“ B” :5],[“ C”:7,“ A”:2,“ B”:5],[“ C”:7,“ A”:3,“ B”:5],[“ C”:8 ,“ A”:1,“ B”:5],[“ C”:8,“ A”:2,“ B”:5],[“ C”:8,“ A”:3,“ B” :5],[“ C”:9,“ A”:1,“ B”:5],[“ C”:9,“ A”:2,“ B”:5],[“ C”:9 ,“ A”:3,“ B”:5],[“ B”:6,“ C”:7,“ A”:1],[“ B”:6,“ C”:7,“ A” :2],[“ B”:6,“ C”:7,“ A”:3],[“ B”:6,“ A”:1,“ C”:8],[“ B”:6 ,“ A”:2,“ C”:8],[“ B”:6,“ A”:3,“ C”:8],[“ B”:6,“ A”:1,“ C” :9],[“ B”:6,“ A”:2,“ C”:9],[“ B”:6,“ A”:3,“ C”:9]]
27
答案 1 :(得分:0)
您确定最后需要一系列词典吗?如果没有,那么这是一个交错的键/值对数组:
let keyValuePairArrays =
["A": [1, 2, 3], "B": [4, 5, 6], "C": [7, 8, 9]]
.sorted(\.key)
.map { key, value in
value.map { (key, $0) }
}
.combinations
如果您真的需要字典,只需将其映射即可! ?
keyValuePairArrays.map(Dictionary.init)
支持代码:
public extension Sequence where Element: Sequence {
var combinations: [[Element.Element]] {
guard let initialResult = ( first?.map { [$0] } )
else { return [] }
return dropFirst().reduce(initialResult) { combinations, iteration in
combinations.flatMap { combination in
iteration.map { combination + [$0] }
}
}
}
}
public extension Sequence {
/// The first element of the sequence.
/// - Note: `nil` if the sequence is empty.
var first: Element? {
var iterator = makeIterator()
return iterator.next()
}
/// Sorted by a common `Comparable` value.
func sorted<Comparable: Swift.Comparable>(
_ comparable: (Element) throws -> Comparable
) rethrows -> [Element] {
try sorted(comparable, <)
}
/// Sorted by a common `Comparable` value, and sorting closure.
func sorted<Comparable: Swift.Comparable>(
_ comparable: (Element) throws -> Comparable,
_ areInIncreasingOrder: (Comparable, Comparable) throws -> Bool
) rethrows -> [Element] {
try sorted {
try areInIncreasingOrder(comparable($0), comparable($1))
}
}
}