36

How do I split a deck of cards? I have an array made and a random card dealer, but have no idea how to split the deck.

Thanks everyone for the help! I now have a working card app, did run into other problems but they were solved quickly.

1

5 Answers 5

32

You can make an extension so it can return an array of two arrays, working with Ints, Strings, etc:

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]]

But returning a named tuple is even better, because it enforces the fact that you expect exactly two arrays as a result:

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"]

Note: credits goes to Andrei and Qbyte for giving the first correct answer, I'm just adding info.

Sign up to request clarification or add additional context in comments.

2 Comments

Named tuple is definitely the better way to go. It lets the compiler enforce that you only expect two arrays
Agreed. :) I've slightly modified the wording of my answer according to your comment.
21

You can use subscript range

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: above code is for Swift 2, maybe for Swift 3 is a more convenient way.

1 Comment

You probably want to have separate arrays instead is ArraySlice. So Array(leftSplit) would give the desired result.
16

Swift

More generic solution to split the array into chunks the answer from this 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)

1 Comment

A little misleading from what the question was asking. This doesn't really help split something in half.If I specify 2 then I get several arrays with a size of 2 each. If I specify half of the count then when the count is odd I will get an extra array with one element.
7

And one more realization of previously provided ideas. Firstly, up to Swift current documentation, it is better to choose names in past simple tense for functions that produce some result and present tense for mutating ones. As second, as for me, it is better to choose half adding count % 2 to give more uniformed result.

Here is it:

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))
    }
}

And results:

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], [])
([], [])

1 Comment

The past tense of 'split' is still 'split'. To follow the guidelines you're referring to it's probably best to find a synonym for split which produces a different spelling in the past tense.
3

You can create an extension on SequenceType, and create a function named divide.

This function would iterate through the elements of the sequence while placing those that match the predicate into one array (slice) and those that do not match into another array (remainder).

The function returns a tuple containing the slice and the 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)
    }

}

This is an example

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.