【问题标题】:How to split an array in half in Swift?如何在 Swift 中将数组分成两半?
【发布时间】:2015-08-18 13:41:50
【问题描述】:

如何拆分一副牌?我有一个阵列和一个随机发牌员,但不知道如何拆分牌组。

感谢大家的帮助!我现在有一个工作卡应用程序,确实遇到了其他问题,但很快就解决了。

【问题讨论】:

标签: arrays swift


【解决方案1】:

你可以做一个扩展,让它返回一个由两个数组组成的数组,使用 Ints、Strings 等:

extension Array {
    func split() -> [[Element]] {
        let ct = self.count
        let half = ct / 2
        let leftSplit = self[0 ..< half]
        let rightSplit = self[half ..< ct]
        return [Array(leftSplit), Array(rightSplit)]
    }
}

let deck = ["J", "Q", "K", "A"]
let nums = [0, 1, 2, 3, 4]

deck.split() // [["J", "Q"], ["K", "A"]]
nums.split() // [[0, 1], [2, 3, 4]]

但是返回一个命名的元组更好,因为它强制你期望结果是两个数组的事实:

extension Array {
    func split() -> (left: [Element], right: [Element]) {
        let ct = self.count
        let half = ct / 2
        let leftSplit = self[0 ..< half]
        let rightSplit = self[half ..< ct]
        return (left: Array(leftSplit), right: Array(rightSplit))
    }
}

let deck = ["J", "Q", "K", "A"]

let splitDeck = deck.split()
print(splitDeck.left) // ["J", "Q"]
print(splitDeck.right) // ["K", "A"]

注意:感谢 Andrei 和 Qbyte 给出了第一个正确答案,我只是在添加信息。

【讨论】:

  • 命名元组绝对是更好的选择。它让编译器强制你只期望两个数组
  • 同意。 :) 我根据您的评论稍微修改了我的回答措辞。
【解决方案2】:

可以使用下标范围

let deck: [String] = ["J", "Q", "K", "A"]

// use ArraySlice only for transient computation
let leftSplit: ArraySlice<String> = deck[0 ..< deck.count / 2] // "J", "Q"
let rightSplit: ArraySlice<String> = deck[deck.count / 2 ..< deck.count] // "K", "A"

// make arrays from ArraySlice
let leftDeck: [String] = Array(leftSplit) // "J", "Q"
let rightDeck: [String] = Array(rightSplit) // "K", "A"

编辑:以上代码适用于 Swift 2,也许 Swift 3 是更方便的方式。

【讨论】:

  • 您可能想要单独的数组而不是ArraySlice。所以Array(leftSplit) 会给出想要的结果。
【解决方案3】:

斯威夫特

将数组拆分为块的更通用解决方案来自link的答案

extension Array {
    func chunked(into size: Int) -> [[Element]] {
        return stride(from: 0, to: count, by: size).map {
            Array(self[$0 ..< Swift.min($0 + size, count)])
        }
    }
}
let numbers = Array(1...100)
let result = numbers.chunked(into: 5)

【讨论】:

  • 对问题的要求有点误导。这并不能真正帮助将某些东西分成两半。如果我指定 2,那么我会得到几个数组,每个数组的大小为 2。如果我指定一半的count,那么当计数为奇数时,我将得到一个包含一个元素的额外数组。
【解决方案4】:

您可以在SequenceType 上创建一个扩展,并创建一个名为divide 的函数。

此函数将遍历序列的元素,同时将与谓词匹配的元素放入一个数组 (slice),将不匹配的元素放入另一个数组 (remainder)。

该函数返回一个包含sliceremainder 的元组。

extension SequenceType {

    /**
     Returns a tuple with 2 arrays.
     The first array (the slice) contains the elements of self that match the predicate.
     The second array (the remainder) contains the elements of self that do not match the predicate.
     */
    func divide(@noescape predicate: (Self.Generator.Element) -> Bool) -> (slice: [Self.Generator.Element], remainder: [Self.Generator.Element]) {
        var slice:     [Self.Generator.Element] = []
        var remainder: [Self.Generator.Element] = []
        forEach {
            switch predicate($0) {
            case true  : slice.append($0)
            case false : remainder.append($0)
            }
        }
        return (slice, remainder)
    }

}

这是一个例子

let tuple = [1, 2, 3, 4, 5].divide({ $0 >= 3 })
tuple.slice     // [3, 4, 5]
tuple.remainder // [1, 2]

【讨论】:

    【解决方案5】:

    还有一个对先前提供的想法的实现。首先,根据 Swift 当前的文档,最好为产生某些结果的函数选择过去简单时的名称,而为变异函数选择现在时。 其次,对于我来说,最好选择半加 count % 2 以得到更统一的结果。

    这里是:

    extension Array {
        func devided() -> ([Element], [Element]) {
            let half = count / 2 + count % 2
            let head = self[0..<half]
            let tail = self[half..<count]
    
            return (Array(head), Array(tail))
        }
    }
    

    结果:

    let set1 = [1, 2, 3, 4, 5, 6, 7,8]
    let set2 = [1, 2, 3, 4, 5]
    let set3 = [1]
    let set4 = [Int]()
    
    print(set1.devided())
    print(set2.devided())
    print(set3.devided())
    print(set4.devided())
    
    ([1, 2, 3, 4], [5, 6, 7, 8])
    ([1, 2, 3], [4, 5])
    ([1], [])
    ([], [])
    

    【讨论】:

    • 'split' 的过去时仍然是'split'。要遵循您所指的准则,最好找到 split 的同义词,它会在过去时产生不同的拼写。
    猜你喜欢
    • 2023-01-17
    • 1970-01-01
    • 2020-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-22
    • 2022-06-12
    相关资源
    最近更新 更多