我遇到了一个需要成对迭代数组的问题。最好的方法是什么?或者,作为替代方案,将数组转换为数组对的最佳方法是什么(然后可以正常迭代)?
这是我得到的最好的。它需要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)
答案 0 :(得分:19)
你可以映射步幅而不是迭代它 允许将结果作为常量:
let input = [1, 2, 3, 4, 5, 6]
let output = stride(from: 0, to: input.count - 1, by: 2).map {
(input[$0], input[$0+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[$0], input[$0+1]) } ) {
print(left, right)
}
答案 1 :(得分:4)
我认为这不比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($0) }
let output = input.pairs.map{$0}
print(output) //->[(1, 2), (3, 4), (5, 6)]
答案 2 :(得分:3)
这是@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)]
答案 3 :(得分:1)
现在可以作为
Sequence.chunks(ofCount: 2)
的 swift-algorithms
package
for (left, right) in input.chunks(ofCount: 2) {
print(left, right)
}
答案 4 :(得分:0)
您不需要自定义类型,例如上述答案所规定的PairIterator
。获得配对的序列是单线的:
let xs = [1, 2, 3]
for pair in zip(xs, xs.dropFirst()) {
print(pair) // (1, 2) (2, 3)
}
如果您打算重复使用该方法,可以在扩展内放置一个pair方法:
extension Sequence {
func pairs() -> AnySequence<(Element, Element)> {
AnySequence(zip(self, self.dropFirst()))
}
}