Как разделить массив пополам в 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"]

Примечание: кредиты передаются Андрею и 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"

EDIT: код выше для Swift 2, возможно, для Swift 3 это более удобный способ.

Ответ 3

Swift

Более общее решение для разделения массива на куски - ответ по этой ссылке

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)

Ответ 4

Вы можете создать расширение на SequenceType и создать функцию с именем divide.

Эта функция будет перебирать элементы последовательности, помещая те, которые соответствуют предикату, в один массив (slice) и те, которые не совпадают с другим массивом (remainder).

Функция возвращает кортеж, содержащий slice и remainder.

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 splitted() -> ([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.splitted())
print(set2.splitted())
print(set3.splitted())
print(set4.splitted())

([1, 2, 3, 4], [5, 6, 7, 8])
([1, 2, 3], [4, 5])
([1], [])
([], [])