Swift: Picking two random, but unique, elements from an array

swift randomize array
swift random elements from array
swift random number
swift get random object from array
swift get multiple random elements from array
swiftui random array
random selector swift
unique random number generator swift

I would like to initialise an array as follows:

func initRoundsArray(playersArray: [String]) -> [String] {

    let rounds: [String] = [
        "ROUND 1: First player: \(String(playersArray.randomElement()!)), Second player: \(String(playersArray.randomElement()!))",
        "ROUND 2: First player: \(String(playersArray.randomElement()!)), Second player: \(String(playersArray.randomElement()!))",
        "ROUND 3: First player: \(String(playersArray.randomElement()!)), Second player: \(String(playersArray.randomElement()!))"
    ]

    return rounds
}

With the following code in my view controller:

let playersArrayInput: [String] = ["Player 1", "Player 2", "Player 3", "Player 4", "Player 5", "Player 6", "Player 7", "Player 8", "Player 9"]
var arrayOfRounds: [String]?

// Called like so in viewDidLoad:
arrayOfRounds = initRoundsArray(playersArray: playersArrayInput)

However I am struggling to figure out how to pick 2 random and unique elements for each round. For example, arrayOfRounds[0] may currently be "ROUND 1: First player: Player 6, Second player: Player 6".

As initRoundsArray is only called once (arrayOfRounds is later mutated), I don't think it's appropriate to just shuffle the array and pick the first 2 elements, as in that case each round would be with the same 2 players.

I am not sure how to achieve this (or if it is even possible). Ideally all that is necessary is when picking two players for round 1, for example, it is checked that they are different to each other.

You basically need to generate n random elements from an array, which you can do with this algorithm:

func pick<T>(_ n: Int, from array: [T]) -> [T] {
    var copy = array // make a copy so we can make changes
    var result = [T]()
    for _ in 0..<n {
        let randomElementIndex = Int.random(in: 0..<copy.count) // generate random index
        let randomElement = copy[randomElementIndex]
        copy.remove(at: randomElementIndex) // remove the generated element
        result.append(randomElement) // add it to the result
    }
    return result
}

To generate the players for 3 rounds, call this with n=6.

Get random elements from array in Swift, And actually, I got two ways of doing better than the accepted answer: extension Array { /// Picks `n` random elements (partial Fisher-Yates shuffle n else { fatalError("The array has to have at least \(n) unique values") } guard n >= 0 else� Creating random strings and shuffling them (for JavaFX ListView) Scala - How to find the unique items in a List, Array, Vector (sequence) Scala Array class: methods, examples, and syntax

I would go with something like the following:

func extractRandomElementsFromArray<Generic>(_ array: [Generic], numberOfElements: Int) -> [Generic]? {
    guard array.count >= numberOfElements else { return nil }

    var toDeplete = array
    var toReturn = [Generic]()

    while toReturn.count < numberOfElements {
        toReturn.append(toDeplete.remove(at: Int.random(in: 0..<toDeplete.count)))
    }

    return toReturn
}

This should work on any array for any number of elements. Basically we are removing random elements from one array and fill them into another array until the second array has enough elements.

In your case this could be used as:

let playersArrayInput: [String] = ["Player 1", "Player 2", "Player 3", "Player 4", "Player 5", "Player 6", "Player 7", "Player 8", "Player 9"]

let pairArray = extractRandomElementsFromArray(playersArrayInput, numberOfElements: 2)!
let player1 = pairArray[0]
let player2 = pairArray[1]

How to pick a random element from an array in Swift, Learn how to pick a random element from an array in Swift using the If you know that your array is not empty, then go ahead and force� Just to answer your question, you can do this to achieve random array selection: let array = [ "Frodo", "sam", "wise", "gamgee" ] let randomIndex = Int (arc4random_uniform (UInt32 (array.count))) print (array [randomIndex]) The castings are ugly, but I believe they're required unless someone else has another way.

You can make a second array and instead of copy the value to the new array, pop the element to the new array so the second items that you will pop will be another one for sure.

Ex.

func initRoundsArray(playersArray: [String]) -> [String] {

    var playersArrayCoppy = playersArray
    let round1Item = playersArrayCoppy.remove(at: Int.random(in: 0...(playersArrayCoppy.count - 1)))
    let round2Item = playersArrayCoppy.remove(at: Int.random(in: 0...(playersArrayCoppy.count - 1)))
    let round3Item = playersArrayCoppy.remove(at: Int.random(in: 0...(playersArrayCoppy.count - 1)))

    let rounds: [String] = [
        "ROUND 1: First player: \(round1Item), Second player: \(round1Item)",
        "ROUND 2: First player: \(round2Item), Second player: \(round2Item)",
        "ROUND 3: First player: \(round3Item), Second player: \(round3Item)"
    ]
    return rounds
}

Of course you need to add some checks that you have items in the array if is not for sure that the array count is >= 3

EDIT Based On the comments what you probably want is this function

func initRoundsArray(roundsNumber: Int, playersArray: [String]) -> [String] {
    var roundsArray:[String] = []
    for i in 1...roundsNumber {
        var playersArrayCoppy = playersArray
        let player1Item = playersArrayCoppy.remove(at: Int.random(in: 0...(playersArrayCoppy.count - 1)))
        let player2Item = playersArrayCoppy.remove(at: Int.random(in: 0...(playersArrayCoppy.count - 1)))

        let round: String = "ROUND \(i): First player: \(player1Item), Second player: \(player2Item)"
        roundsArray.append(round)
    }
    return roundsArray
}

and you call it with initRoundsArray(roundsNumber: 3, playersArray: ["?","?",..."])

Unique random number generation in Swift, We have what we need: parameters for how many random numbers to generate and a maximum value. Now how do we populate the array? If you are picking random array elements that need to be unpredictable, you should use java.security.SecureRandom rather than Random. That ensures that if somebody knows the last few picks, they won't have an advantage in guessing the next one.

I have ended up using the following code (<ACTION> is just a placeholder):

func initRoundsArray(playersArray: [String]) -> [String] {

    let round1Players = twoRandomPlayers(playersArray: playersArray)
    let round2Players = twoRandomPlayers(playersArray: playersArray)

    let rounds: [String] = [
        "ROUND 1: \(round1players[0]), do <ACTION> to \(round1players[1])",
        "ROUND 2: \(round2players[0]), do <ACTION> to \(round2players[1])",
        "ROUND 3: \(String(playersArray.randomElement()!)), do <ACTION>"
    ]

    return rounds
}

func twoRandomPlayers(playersArray: [String]) -> [String] {
    let shuffledPlayersArray = playersArray.shuffled()

    return Array(shuffledPlayersArray.prefix(2))
}

I will call a separate function each time which returns an array with 2 randomly picked (and unique) players from the playersArray, and use that in the rounds that require 2 players.

I understand this may not be the best way of doing this, but in my final implementation it's likely that the vast majority of rounds will only involve one player, and thus .randomElement() is suitable.

I apologise if the wording in the original question was confusing, but I hope this clarifies things, and thank you very much to everyone for their suggestions/answers :)

Generate random numbers without repetitions, This algorithm will produce random values, in a random order, and with good Once you have a clean set of unique random numbers, you can dump them in to a List the (randomly picked out by myself) values between 7894500 and 7894512 . 2 * sizeof(int)) { //if the amount of bytes occupied by the array is greater then� When creating an object, or a new user, you sometimes need a random unique ID; Let’s get started! Random Numbers in Swift 4.2 and up; Random Numbers Before Swift 4.2; Random Integers with “arc4random_uniform(_:)” Random Doubles with “drand48()” An Easy Function for Random Numbers; Picking a Random Element from an Array; Generating A

First of all, let's suppose that playersArrayInput doesn't have any duplicates.

let playersArrayInput: [String] = ["Player 1", "Player 2", "Player 3", "Player 4", "Player 5", "Player 6", "Player 7", "Player 8", "Player 9"]

An efficient implementation consists of shuffling only the indices :

func initRoundsArray(playersArray: [String]) -> [String] {

    var shuffledIndices = playersArray.indices.shuffled()
    let count = playersArray.count - 1
    var rounds = [String]()
    var i = 0

    while i <= count {
        let round = String(rounds.count + 1)
        if i <= count - 1 {
            switch Bool.random() {
            case true:
                rounds.append("ROUND " +
                    round +
                    ": " +
                    playersArray[shuffledIndices[i]] +
                    ", do <ACTION>")
                i += 1
            default:
                rounds.append("ROUND " +
                    round +
                    ": " +
                    playersArray[shuffledIndices[i]] +
                    ", do <ACTION> to " +
                    playersArray[shuffledIndices[i + 1]])
                i += 2
            }
        } else {
            rounds.append("ROUND " +
                round +
                ": " +
                playersArray[shuffledIndices[count]] +
                ", do <ACTION>")
            break
        }
    }

    return rounds
}

And we could print the result of the call this way :

initRoundsArray(playersArray: playersArrayInput).forEach { print($0) }

yielding for example :

ROUND 1: Player 7, do <ACTION> to Player 1
ROUND 2: Player 8, do <ACTION>
ROUND 3: Player 5, do <ACTION>
ROUND 4: Player 9, do <ACTION> to Player 2
ROUND 5: Player 3, do <ACTION> to Player 6
ROUND 6: Player 4, do <ACTION>

randomElement(), Swift Standard Library Call randomElement() to select a random element from an array or another This example picks a name at random from an array:. Swift 3. These extensions add a shuffle() method to any mutable collection and a shuffled() method to any sequence:. extension MutableCollection where Indices.Iterator.Element == Index { /// Shuffles the contents of this collection.

How to get a random element from an array , Xcode 10.0+. Framework. Swift Standard Library Call randomElement() to select a random element from an array or another collection. This example picks a name at random from an array: let names = ["Zoey" Getting Characters and Bytes. Specifically, you use the Array type to hold elements of a single type, the array’s Element type. An array can store any kind of elements—from integers to strings to classes. Swift makes it easy to create arrays in your code using an array literal: simply surround a comma-separated list of values with square brackets.

Get a random unique element from an Array until all elements have , Swift's arrays, sets, and dictionaries have a randomElement() method that returns one random item from the collection. Because your collection� Choose a random element from a multidimensional array in Python. Most of the time we work with 2-d or 3-d arrays in Python. Let assume you want to pick a random element from it then how to do it? Let see this with an example. In this example, We used numpy.random.choice() function to pick a random element from the multidimensional array.

Random Numbers in Swift (How To) – LearnAppMaking, Both contains 5 equal elements (say 1 to 5), but second array contains one extra How to pick a random element from an array in Swift, Learn how to pick a� randomly select elements of an array. Learn more about matrix . Skip to content. For example I want to select a random element in last row of a matrix.

Comments
  • shuffle your array and then pick elements
  • @dahiya_boy I've discussed that approach in the question itself, penultimate paragraph.
  • you need to shuffle once not for every round
  • @dahiya_boy There may be a different number of players each time, the array provided in the question is just an example. If I were to shuffle as you suggest, how could I then continue to prevent duplicates?
  • @chumps52 Your question is a bit confusing. So a single round must contain 2 different players. But then you want unique pairs through as many rounds as possible. And players may change during execution. Is that what you are trying to do? Like a server starts and people start logging in and logging out so you want to keep making pairs of players for each round any you would like that pairs don't duplicate?
  • That Int.random(in: 0..<n) doesn't look correct since you are depleting items from copy. Assume it had 2 items and n is 2. The first element is correct but the second has 50% chance to roll index 1 but the only valid index left is 0 since copy now has only 1 item left in it.
  • @Kamran oops! Fixed now.
  • I've just run that code and it guarantees duplicates: ["ROUND 1: First player: Player 9, Second player: Player 9", "ROUND 2: First player: Player 8, Second player: Player 8", "ROUND 3: First player: Player 7, Second player: Player 7"]
  • no it Doesn't I just added round1Item to First player and SecondPlayer! Butt round1Item is always different from round2Item and round3Item I didn't understand that you want different per player, I thought you wanted per round. If you want different per player you need to call the function per round and use only 2 items
  • Why does ROUND 3 have only one player in it?
  • @ielyamani I mentioned this in the answer briefly, but in the actual implementation some rounds will only involve one player having to do something. The original question didn't mention this as I knew how to implement that already - the question I had was getting 2 non-duplicates in one string/round.