Methods that compute permutations of a collection’s elements, or of a subset of those elements.
The permutations(ofCount:)
method, when called without the ofCount
parameter, returns a sequence of all the different permutations of a
collection’s elements:
let numbers = [10, 20, 30]
for perm in numbers.permutations() {
print(perm)
}
// [10, 20, 30]
// [10, 30, 20]
// [20, 10, 30]
// [20, 30, 10]
// [30, 10, 20]
// [30, 20, 10]
Passing a value for ofCount
generates partial permutations, each with the
specified number of elements:
for perm in numbers.permutations(ofCount: 2) {
print(perm)
}
// [10, 20]
// [10, 30]
// [20, 10]
// [20, 30]
// [30, 10]
// [30, 20]
The permutations or partial permutations are generated in increasing lexicographic order of the collection’s original ordering (rather than the order of the elements themselves). The first permutation will always consist of elements in their original order, and the last will have the elements in the reverse of their original order.
Values that are repeated in the original collection are always treated as separate values in the resulting permutations:
let numbers2 = [20, 10, 10]
for perm in numbers2.permutations() {
print(perm)
}
// [20, 10, 10]
// [20, 10, 10]
// [10, 20, 10]
// [10, 10, 20]
// [10, 20, 10]
// [10, 10, 20]
To generate only unique permutations, use the uniquePermutations(ofCount:)
method:
for perm in numbers2.uniquePermutations() {
print(perm)
}
// [20, 10, 10]
// [10, 20, 10]
// [10, 10, 20]
Given a range, the methods return a sequence of all the different permutations of the given sizes of a collection’s elements in increasing order of size.
let numbers = [10, 20, 30]
for perm in numbers.permutations(ofCount: 0...) {
print(perm)
}
// []
// [10]
// [20]
// [30]
// [10, 20]
// [10, 30]
// [20, 10]
// [20, 30]
// [30, 10]
// [30, 20]
// [10, 20, 30]
// [10, 30, 20]
// [20, 10, 30]
// [20, 30, 10]
// [30, 10, 20]
// [30, 20, 10]
The permutations(ofCount:)
and uniquePermutations(ofCount:)
methods are
declared as Collection
extensions, and return PermutationsSequence
and
UniquePermutationsSequence
instances, respectively:
extension Collection {
public func permutations(ofCount k: Int? = nil) -> PermutationsSequence<Self>
public func permutations<R>(ofCount kRange: R) -> PermutationsSequence<Self>
where R: RangeExpression, R.Bound == Int
}
extension Collection where Element: Hashable {
public func uniquePermutations(ofCount k: Int? = nil) -> UniquePermutationsSequence<Self>
public func uniquePermutations<R>(ofCount kRange: R) -> UniquePermutationsSequence<Self>
where R: RangeExpression, R.Bound == Int
}
Since both result types need to store an array of the collection’s
indices and mutate the array to generate each permutation, they only
have Sequence
conformance. Adding Collection
conformance would require
storing the array in the index type, which would in turn lead to copying the
array at every index advancement. The PermutationsSequence
and
UniquePermutationsSequence
types conforms to LazySequenceProtocol
when their
base type conforms.
Calling permutations()
is an O(1) operation. Creating the iterator for a
PermutationsSequence
instance and each call to
PermutationsSequence.Iterator.next()
is an O(n) operation.
Calling uniquePermutations()
is an O(n) operation, because it preprocesses
the collection to find duplicate elements. Creating the iterator for and each
call to next()
is also an O(n) operation.
See the "Naming" section for combinations(ofCount:)
for detail.
C++: The <algorithm>
library defines a next_permutation
function that
advances an array of comparable values through their lexicographic orderings.
This function is very similar to the uniquePermutations(ofCount:)
method.
Rust/Ruby/Python: Rust, Ruby, and Python all define functions with
essentially the same semantics as the permutations(ofCount:)
method
described here.