Swift:配对数组元素的最佳方式是什么
Swift: What's the best way to pair up elements of an Array
我遇到了一个需要成对迭代数组的问题。最好的方法是什么?或者,作为替代方案,将数组转换为对数组(然后可以正常迭代)的最佳方法是什么?
这是我得到的最好的。它要求 output
成为 var
,而且它不是很漂亮。有没有更好的方法?
let input = [1, 2, 3, 4, 5, 6]
var output = [(Int, Int)]()
for i in stride(from: 0, to: input.count - 1, by: 2) {
output.append((input[i], input[i+1]))
}
print(output) // [(1, 2), (3, 4), (5, 6)]
// let desiredOutput = [(1, 2), (3, 4), (5, 6)]
// print(desiredOutput)
你可以映射步幅而不是迭代它,那
允许将结果作为 常量:
let input = [1, 2, 3, 4, 5, 6]
let output = stride(from: 0, to: input.count - 1, by: 2).map {
(input[[=10=]], input[[=10=]+1])
}
print(output) // [(1, 2), (3, 4), (5, 6)]
如果你只需要遍历对并且给定的数组很大
那么避免创建中间体可能是有利的
具有惰性映射的数组:
for (left, right) in stride(from: 0, to: input.count - 1, by: 2)
.lazy
.map( { (input[[=11=]], input[[=11=]+1]) } ) {
print(left, right)
}
我认为这并不比 Martin R 的好,但 OP 似乎需要其他东西...
struct PairIterator<C: IteratorProtocol>: IteratorProtocol {
private var baseIterator: C
init(_ iterator: C) {
baseIterator = iterator
}
mutating func next() -> (C.Element, C.Element)? {
if let left = baseIterator.next(), let right = baseIterator.next() {
return (left, right)
}
return nil
}
}
extension Sequence {
var pairs: AnySequence<(Self.Iterator.Element,Self.Iterator.Element)> {
return AnySequence({PairIterator(self.makeIterator())})
}
}
input.pairs.forEach{ print([=10=]) }
let output = input.pairs.map{[=10=]}
print(output) //->[(1, 2), (3, 4), (5, 6)]
这是@OOPer 答案的一个版本,它适用于列表中奇数个元素。当然,如果你愿意,你可以不遵守 CustomStringConvertible
。但它为这个例子提供了更漂亮的输出。 :)
struct Pair<P: CustomStringConvertible>: CustomStringConvertible {
let left: P
let right: P?
var description: String {
if let right = right {
return "(\(left.description), \(right.description)"
}
return "(\(left.description), nil)"
}
}
struct PairIterator<C: IteratorProtocol>: IteratorProtocol where C.Element: CustomStringConvertible {
private var baseIterator: C
init(_ iterator: C) {
baseIterator = iterator
}
mutating func next() -> Pair<C.Element>? {
if let left = baseIterator.next() {
return Pair(left: left, right: baseIterator.next())
}
return nil
}
}
extension Sequence where Element: CustomStringConvertible {
var pairs: AnySequence<Pair<Self.Element>> {
return AnySequence({PairIterator(self.makeIterator())})
}
}
let input: [Int] = [1,2,3,4,5,6,7]
print(input.pairs)
print(Array(input.pairs))
//output:
AnySequence<Pair<Int>>(_box: Swift._SequenceBox<Swift._ClosureBasedSequence<__lldb_expr_27.PairIterator<Swift.IndexingIterator<Swift.Array<Swift.Int>>>>>)
[(1, 2, (3, 4, (5, 6, (7, nil)]
您不需要自定义类型,例如上述答案规定的 PairIterator
。获得配对序列是 one-liner:
let xs = [1, 2, 3]
for pair in zip(xs, xs.dropFirst()) {
print(pair) // (1, 2) (2, 3)
}
如果你打算重用它,你可以在扩展中放置一个 pairs 方法:
extension Sequence {
func pairs() -> AnySequence<(Element, Element)> {
AnySequence(zip(self, self.dropFirst()))
}
}
现在可用
Sequence.chunks(ofCount: 2)
of the swift-algorithms
package
for chunk in input.chunks(ofCount: 2) {
print(chunk)
}
我遇到了一个需要成对迭代数组的问题。最好的方法是什么?或者,作为替代方案,将数组转换为对数组(然后可以正常迭代)的最佳方法是什么?
这是我得到的最好的。它要求 output
成为 var
,而且它不是很漂亮。有没有更好的方法?
let input = [1, 2, 3, 4, 5, 6]
var output = [(Int, Int)]()
for i in stride(from: 0, to: input.count - 1, by: 2) {
output.append((input[i], input[i+1]))
}
print(output) // [(1, 2), (3, 4), (5, 6)]
// let desiredOutput = [(1, 2), (3, 4), (5, 6)]
// print(desiredOutput)
你可以映射步幅而不是迭代它,那 允许将结果作为 常量:
let input = [1, 2, 3, 4, 5, 6]
let output = stride(from: 0, to: input.count - 1, by: 2).map {
(input[[=10=]], input[[=10=]+1])
}
print(output) // [(1, 2), (3, 4), (5, 6)]
如果你只需要遍历对并且给定的数组很大 那么避免创建中间体可能是有利的 具有惰性映射的数组:
for (left, right) in stride(from: 0, to: input.count - 1, by: 2)
.lazy
.map( { (input[[=11=]], input[[=11=]+1]) } ) {
print(left, right)
}
我认为这并不比 Martin R 的好,但 OP 似乎需要其他东西...
struct PairIterator<C: IteratorProtocol>: IteratorProtocol {
private var baseIterator: C
init(_ iterator: C) {
baseIterator = iterator
}
mutating func next() -> (C.Element, C.Element)? {
if let left = baseIterator.next(), let right = baseIterator.next() {
return (left, right)
}
return nil
}
}
extension Sequence {
var pairs: AnySequence<(Self.Iterator.Element,Self.Iterator.Element)> {
return AnySequence({PairIterator(self.makeIterator())})
}
}
input.pairs.forEach{ print([=10=]) }
let output = input.pairs.map{[=10=]}
print(output) //->[(1, 2), (3, 4), (5, 6)]
这是@OOPer 答案的一个版本,它适用于列表中奇数个元素。当然,如果你愿意,你可以不遵守 CustomStringConvertible
。但它为这个例子提供了更漂亮的输出。 :)
struct Pair<P: CustomStringConvertible>: CustomStringConvertible {
let left: P
let right: P?
var description: String {
if let right = right {
return "(\(left.description), \(right.description)"
}
return "(\(left.description), nil)"
}
}
struct PairIterator<C: IteratorProtocol>: IteratorProtocol where C.Element: CustomStringConvertible {
private var baseIterator: C
init(_ iterator: C) {
baseIterator = iterator
}
mutating func next() -> Pair<C.Element>? {
if let left = baseIterator.next() {
return Pair(left: left, right: baseIterator.next())
}
return nil
}
}
extension Sequence where Element: CustomStringConvertible {
var pairs: AnySequence<Pair<Self.Element>> {
return AnySequence({PairIterator(self.makeIterator())})
}
}
let input: [Int] = [1,2,3,4,5,6,7]
print(input.pairs)
print(Array(input.pairs))
//output:
AnySequence<Pair<Int>>(_box: Swift._SequenceBox<Swift._ClosureBasedSequence<__lldb_expr_27.PairIterator<Swift.IndexingIterator<Swift.Array<Swift.Int>>>>>)
[(1, 2, (3, 4, (5, 6, (7, nil)]
您不需要自定义类型,例如上述答案规定的 PairIterator
。获得配对序列是 one-liner:
let xs = [1, 2, 3]
for pair in zip(xs, xs.dropFirst()) {
print(pair) // (1, 2) (2, 3)
}
如果你打算重用它,你可以在扩展中放置一个 pairs 方法:
extension Sequence {
func pairs() -> AnySequence<(Element, Element)> {
AnySequence(zip(self, self.dropFirst()))
}
}
现在可用
Sequence.chunks(ofCount: 2)
of the swift-algorithms
package
for chunk in input.chunks(ofCount: 2) {
print(chunk)
}