【Swift】配列をペアに変換して処理する方法


# はじめに

[配列を処理するときに次の要素を扱う方法](https://qiita.com/akeome/items/514c077cfc460d7d2382)の記事を参考にいろいろとアレンジしてみました。
また、空配列がやってきたりして、ペアの生成に失敗したときにエラーにならないことも確認しながら書いてみました。

## パターン1：最後の要素のペアにはnilを入れたい場合

```swift
extension Array {
    var pair: [(Element, Element?)] {
        var copy: [Element?] = self
        copy.append(nil)
        return enumerated().map { ($0.element, copy[$0.offset + 1]) }
    }
}

let nums = [1,2,3]
nums.pair.forEach { num1, num2 in
    guard let num2 = num2 else {
        return
    }
    print("\(num1) * \(num2) = \(num1 * (num2))")
}
//  出力
//  1 * 2 = 2
//  2 * 3 = 6

let empty: [Int]  = []
empty.pair.forEach { num1, num2 in
    guard let num2 = num2 else {
        return
    }
    print("\(num1) * \(num2) = \(num1 * (num2))")
}
//  出力
//  なし
```

## パターン2：最後の要素のペアには先頭の要素とペアにしたい場合

```swift
extension Array {
    var pair: [(Element, Element)]? {
        var copy: [Element] = self
        guard let first = self.first else { // このguard文で早期リターンさせないと空の配列が来たときに実行時エラーになる
            return nil // 空配列を返却してもよいがpairが作れなかったという意味も込めてnilを返す
        }
        copy.append(first)
        return enumerated().map { ($0.element, copy[$0.offset + 1]) }
    }
}

let nums = [1,2,3]
nums.pair?.forEach { num1, num2 in
    print("\(num1) * \(num2) = \(num1 * (num2))")
}
// 出力
// 1 * 2 = 2
// 2 * 3 = 6
// 3 * 1 = 3 ← 最後のペアには先頭の要素が入る

let empty: [Int]  = []
empty.pair?.forEach { num1, num2 in
    print("\(num1) * \(num2) = \(num1 * (num2))")
}
// 出力
// なし
```

## パターン3：最後の要素のペアを自由に変更させたい場合

```swift
extension Array {
    func pair(lastPairIndex: Int? = 0) -> [(Element, Element?)] {
        var copy: [Element?] = self
        var lastPair: Element?
        if let lastPairIndex = lastPairIndex, self.indices.contains(lastPairIndex) {
            lastPair = self[lastPairIndex]
        } else {
            lastPair = nil
        }
        copy.append(lastPair)
        return enumerated().map { ($0.element, copy[$0.offset + 1]) }
    }
}

let nums = [1,2,3]
nums.pair(lastPairIndex: nil).forEach { num1, num2 in
    guard let num2 = num2 else {
        return
    }
    print("\(num1) * \(num2) = \(num1 * (num2))")
}
// 出力
// 1 * 2 = 2
// 2 * 3 = 6

nums.pair().forEach { num1, num2 in
    guard let num2 = num2 else {
        return
    }
    print("\(num1) * \(num2) = \(num1 * (num2))")
}
// 出力
// 1 * 2 = 2
// 2 * 3 = 6
// 3 * 1 = 3

// こういうこと（最後は最後の値とペアになる）も可能
nums.pair(lastPairIndex: nums.indices.last).forEach { num1, num2 in
    guard let num2 = num2 else {
        return
    }
    print("\(num1) * \(num2) = \(num1 * (num2))")
}
// 出力
// 1 * 2 = 2
// 2 * 3 = 6
// 3 * 3 = 9 ← 最後は最後の値とペアになる


let empty: [Int]  = []
empty.pair().forEach { num1, num2 in
    guard let num2 = num2 else {
        return
    }
    print("\(num1) * \(num2) = \(num1 * (num2))")
}
// 出力
// なし

empty.pair(lastPairIndex: nil).forEach { num1, num2 in
    guard let num2 = num2 else {
        return
    }
    print("\(num1) * \(num2) = \(num1 * (num2))")
}
// 出力
// なし

// こいうことしてもエラーにはならない
empty.pair(lastPairIndex: 100).forEach { num1, num2 in
    guard let num2 = num2 else {
        return
    }
    print("\(num1) * \(num2) = \(num1 * (num2))")
}
// 出力
// なし
```

# さいごに

Array の Array[Index] でのアクセスは実行時まで、エラーに気づかないので `self.indices.contains(Index)` で Index が存在することを確認してからアクセスした方がいいです。

というよりも、そのようなアクセスをする処理を書かないのがベターです。