Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Array - Difference between "Int.random(in: 0...25)" and "randomElement()"

I recently started learning swift via an online course.

I was given the Task to generate a passwort out of a given Array containing characters. We learned mainly two code examples to randomly choose one.

  1. variable[Int.random(in: 0...25)]
  2. variable.randomElement()

Both work just fine when pulling out one single element out of an array but only "variable[Int.random(in: 0...25)" when combined multiple times with a plus (+).

Why is that?


I looked up the documentation but couldn't find an answer

https://developer.apple.com/documentation/swift/array/2994747-randomelement


Explanation:

This code works:

let alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]

//The number of letters in alphabet equals 26
var password = alphabet[Int.random(in: 0...25)] + alphabet[Int.random(in: 0...25)] + alphabet[Int.random(in: 0...25)] + alphabet[Int.random(in: 0...25)] + alphabet[Int.random(in: 0...25)] + alphabet[Int.random(in: 0...25)]  

print(password)

This code does not work, because "randomElement()" gets grey after combining multiple with plus (why?)

let alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]

//The number of letters in alphabet equals 26
var password = alphabet.randomElement() + alphabet.randomElement() + alphabet.randomElement() + alphabet.randomElement() + alphabet.randomElement() + alphabet.randomElement()  

print(password)

Edit: Thanks for the fast explanation guys !

like image 513
AWSMpb Avatar asked Oct 23 '19 14:10

AWSMpb


3 Answers

The difference is that randomElement returns an optional string ( String?), as opposed to the subscript that returns a non-optional. Why does randomElement return an optional string? Well, what if the array is empty?

And Swift can't figure out how to add 2 optional strings (let alone 6! So it just gives up). One way to fix this is to force-unwrap the return values of randomElement:

let password = alphabet.randomElement()! + alphabet.randomElement()! + alphabet.randomElement()! + alphabet.randomElement()! + alphabet.randomElement()! + alphabet.randomElement()!

We know the array is not empty, so we can safely force-unwrap here.

Arguably, randomElement is the better method to use here, because it forces you to think about the situation where the array is empty, and handle it accordingly. The first approach with subscripts doesn't have checks for whether the array is empty, or whether the indices are correct, etc.

like image 99
Sweeper Avatar answered Oct 20 '22 13:10

Sweeper


This is because of the different return type between the two approaches.

Indexing an array of strings return, as you would expect, the String at that index.

However the .randomElement() function has a different signature: it return an optional element of the sequence, in your case an optional string (String?).

The '+' operator is defined for strings, but not for optional Strings. To add together the elements returned from .randomElement() you would need to unwrap them first. Given you have a closed sequence you it would be safe to force unwrap them with '!':

var password = alphabet.randomElement()! + alphabet.randomElement()! + alphabet.randomElement()! + alphabet.randomElement()! + alphabet.randomElement()! + alphabet.randomElement()! 
like image 44
flanker Avatar answered Oct 20 '22 12:10

flanker


Instead of writing many times the same code, try some loops:

let alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
var i = 0
var temp = ""
    //The number of letters in alphabet equals 26
while i < 6 {
    temp = temp + alphabet[Int.random(in: 0...25)]
    i += 1
}
let password = temp
    
print(password)
like image 29
Jakub K Avatar answered Oct 20 '22 13:10

Jakub K