如何交错两个数组?

时间:2016-01-22 16:46:12

标签: arrays swift array-merge

如果我有两个数组,例如

let one = [1,3,5]
let two = [2,4,6]

我想以下列模式合并/交错数组[one [0],two [0],one [1],two [1]等....]

//prints [1,2,3,4,5,6]
let comibned = mergeFunction(one, two)
print(combined)

实现组合功能的好方法是什么?

func mergeFunction(one: [T], _ two: [T]) -> [T] {
    var mergedArray = [T]()
    //What goes here
    return mergedArray
}

4 个答案:

答案 0 :(得分:26)

如果两个阵列的长度相同,那么这是一个可能的解决方案:

let one = [1,3,5]
let two = [2,4,6]

let merged = zip(one, two).flatMap { [$0, $1] }

print(merged) // [1, 2, 3, 4, 5, 6]

这里zip()并行枚举数组并返回一个序列 对(2元素元组)与每个数组中的一个元素。 flatMap()从每对创建一个2元素数组并连接结果。

如果数组的长度不同,则附加 结果中较长数组的额外元素:

func mergeFunction<T>(one: [T], _ two: [T]) -> [T] {
    let commonLength = min(one.count, two.count)
    return zip(one, two).flatMap { [$0, $1] } 
           + one.suffixFrom(commonLength)
           + two.suffixFrom(commonLength)
}

Swift 3的更新:

func mergeFunction<T>(_ one: [T], _ two: [T]) -> [T] {
    let commonLength = min(one.count, two.count)
    return zip(one, two).flatMap { [$0, $1] } 
           + one.suffix(from: commonLength)
           + two.suffix(from: commonLength)
}

答案 1 :(得分:6)

如果你只是想交错两个数组,你可以这样做:

let maxIndex = max(one.count, two.count)
var mergedArray = Array<T>()
for index in 0..<maxIndex {
    if index < one.count { mergedArray.append(one[index]) }
    if index < two.count { mergedArray.append(two[index]) }
}

return mergedArray

答案 2 :(得分:0)

使用Swift 4.2,您可以使用以下三个Playground示例之一来解决您的问题。


#1。使用zip(_:_:)函数和Collection的{​​{3}}方法

let one = [1, 3, 5]
let two = [2, 4, 6]

let array = zip(one, two).flatMap({ [$0, $1] })
print(array) // print: [1, 2, 3, 4, 5, 6]

Apple flatMap(_:)

  

如果传递给zip(_:_:)的两个序列的长度不同,则所得序列与较短序列的长度相同。


#2。使用states函数

let one = [1, 3, 5]
let two = [2, 4, 6]

let unfoldSequence = sequence(state: (false, one.makeIterator(), two.makeIterator()), next: { state -> Int? in
    state.0.toggle()
    return state.0 ? state.1.next() : state.2.next()
})
let array = Array(unfoldSequence)
print(array) // print: [1, 2, 3, 4, 5, 6]

#3。使用AnyIterator的{​​{3}}初始化程序

let one = [1, 3, 5]
let two = [2, 4, 6]

var oneIterator = one.makeIterator()
var twoIterator = two.makeIterator()
var state = false

let anyIterator = AnyIterator<Int> {
    state.toggle()
    return state ? oneIterator.next() : twoIterator.next()
}

let array = Array(anyIterator)
print(array) // print: [1, 2, 3, 4, 5, 6]

作为替代方案,您可以将迭代器包装在sequence(state:next:)实例中:

let one = [1, 3, 5]
let two = [2, 4, 6]

let anySequence = AnySequence<Int>({ () -> AnyIterator<Int> in
    var oneIterator = one.makeIterator()
    var twoIterator = two.makeIterator()
    var state = false

    return AnyIterator<Int> {
        state.toggle()
        return state ? oneIterator.next() : twoIterator.next()
    }
})

let array = Array(anySequence)
print(array) // print: [1, 2, 3, 4, 5, 6]

答案 3 :(得分:0)

  /// Alternates between the elements of two sequences.
  /// - Parameter keepSuffix:
  /// When `true`, and the sequences have different lengths,
  /// the suffix of `interleaved`  will be the suffix of the longer sequence.
  func interleaved<Sequence: Swift.Sequence>(
    with sequence: Sequence,
    keepingLongerSuffix keepSuffix: Bool = false
  ) -> AnySequence<Element>
  where Sequence.Element == Element {
    keepSuffix
    ? .init { () -> AnyIterator<Element> in
      var iterators = (
        AnyIterator( self.makeIterator() ),
        AnyIterator( sequence.makeIterator() )
      )
      return .init {
        defer { iterators = (iterators.1, iterators.0) }
        return iterators.0.next() ?? iterators.1.next()
      }
    }
    : .init(
      zip(self, sequence).lazy.flatMap { [$0, $1] }
    )
  }
let oddsTo7 = stride(from: 1, to: 7, by: 2)
let evensThrough10 = stride(from: 2, through: 10, by: 2)
let oneThrough6 = Array(1...6)

XCTAssertEqual(
  Array( oddsTo7.interleaved(with: evensThrough10) ),
  oneThrough6
)

XCTAssertEqual(
  Array(
    oddsTo7.interleaved(with: evensThrough10, keepingLongerSuffix: true)
  ),
  oneThrough6 + [8, 10]
)