将快速数组减少为成对的另一个

时间:2018-10-17 08:16:55

标签: arrays swift algorithm data-structures functional-programming

我有一个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)
            }
    }
}

2 个答案:

答案 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