我有一个Int
的数组。我需要以某种方式更改它以获得新的Int
对数组(元组数组)。
let a = [1, 2, 3, 4, 5]
// How to get array b which is
let b: [(Int, Int?)] // And it should be [(1, 2), (3, 4), (5, nil)]
显而易见的解决方案是使用循环。但是我想知道这是否是更具声明性的方式。像map
这样的东西需要两个参数
// Something like this
let b = a.tupleMap { ($0, $1) }
更新: 相关solution中有一个很棒的question。
基于此,我添加了自己的reduce
方法:
extension Collection {
func reduceByPairs<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element, Element?) throws -> Result) rethrows -> Result {
return try sequence(state: makeIterator()) { it in
it.next().map { ($0, it.next()) }
}
.reduce(initialResult) {
try nextPartialResult($0, $1.0, $1.1)
}
}
}
答案 0 :(得分:0)
您可以尝试以下方法:
extension Array {
func tupleMap(_ transform: (Element, Element?) -> (Element, Element?) = { ($0,$1) }) -> [(Element, Element?)] {
guard count > 0
else { return [] }
var result = [(Element, Element?)]()
var value1 = self[0]
var value2 : Element? = nil
for i in 0..<count {
if i % 2 == 0 {
value1 = self[i]
}
else {
value2 = self[i]
result.append(transform(value1, value2))
}
}
if count % 2 == 1 {
result.append(transform(value1, nil))
}
return result
}
}
然后您可以通过以下方式使用它:
let b = a.tupleMap { ($0, $1) }
甚至是这样:
let b = a.tupleMap()
编辑:
或者如Leo在这里建议的:Iterate over collection two at a time in Swift
这里是一个简短得多的版本:
extension Array {
func tupleMap(_ transform: (Element, Element?) -> (Element, Element?) = { ($0,$1) }) -> [(Element, Element?)] {
return stride(from: 0, to: count, by: 2).map {
transform(self[$0], $0 < count-1 ? self[$0.advanced(by: 1)] : nil)
}
}
}
答案 1 :(得分:0)
我会做这样的事情。
let array = [1, 2, 3, 4, 5]
let pairedArray = array
.enumerated()
.map { return ($0.element, array.count > $0.offset + 1 ? array[$0.offset + 1] : nil) }
.enumerated()
.filter({ $0.offset % 2 == 0 })
.map { $0.element }
print(pairedArray) // [(1, Optional(2)), (3, Optional(4)), (5, nil)]
显然,元组的第二个元素是Optional
,因为您希望在没有值时能够拥有nil
。