0

I have an array with 7 objects inside it, and am using the Array.count to get the number of objects inside the array.

I'm then using Int.random(in: 0 ... arrayMax) to get a random object from the array. Yet, because there are 7 objects in the array, and the .count will return 7, I'll every once in a while get an error, because 7 is obviously 6.

I've tried to solve this by going like this:

let nTMax = Array.count
let nTSelection = Int.random(in: 0 ... nTMax)
print (nTMax, nTSelection) 
let nTSelectionProtect = nTSelection -1

but the nTSelectionProtect refuses to be accepted. I was hoping to do a safety calculation so that 7 will always be 6, but I'm not sure how to do it.

How would I do it?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
esaruoho
  • 896
  • 1
  • 7
  • 25
  • Why do this `let nTSelectionProtect = nTSelection -1` if you can produce a valid value from correct range also `nTSelection` may be zer0 so `nTSelectionProtect` will be `-1` – Shehata Gamal May 26 '19 at 12:15
  • 1
    Note: there is a `randomElement()` call on array that will return an element. It is optional, so: `if element = array.randomElement() { // use the element }`. – vacawama May 26 '19 at 12:24
  • @vacawama thanks, I'll try to modify my code and see if it works! – esaruoho May 26 '19 at 12:25
  • @vacawama unfortunately all i got was an error: "1. Overloads for 'subscript' exist with these partially matching parameter lists: (Int), (Range), (Range), ((UnboundedRange_) -> ())" – esaruoho May 26 '19 at 12:29
  • `randomElement()` gives you a random element from your array, not the index of that element – vacawama May 26 '19 at 12:30
  • see all possible ways here https://stackoverflow.com/questions/24007129/how-does-one-generate-a-random-number-in-apples-swift-language – Shehata Gamal May 26 '19 at 12:31
  • you can do `guard let ele = arr.ranomElement() , let index = arr.index(of:ele) else { return }` – Shehata Gamal May 26 '19 at 12:32
  • @vacawama weirdly enough, I can't use let nTeslaUtterance = AVSpeechUtterance(string: nTeslaQuoteArray.randomElement()) because it will just output an error `Value of optional type 'String?' must be unwrapped to a value of type 'String'` and `Coalesce using '??' to provide a default when the optional value contains 'nil'` and `Force-unwrap using '!' to abort execution if the optional value contains 'nil'` – esaruoho May 26 '19 at 12:34
  • It returns an optional element which needs to be unwrapped: `nTeslaUtterance = AVSpeechUtterance(string: nTeslaQuoteArray.randomElement() ?? "")` – vacawama May 26 '19 at 12:37
  • 1
    `arr.indices` will return the range you need to generate a random index: `let nTSelection = Int.random(in: arr.indices)` – vacawama May 26 '19 at 12:53

1 Answers1

2

It's more safe to use

    let nTSelection = Int.random(in: 0..<nTMax)

This

    let nTSelectionProtect = nTSelection -1

will crash if the random returned is zero, this nTSelection -1 will be -1


You can also fetch a random element with

print(array.randomElement())
esaruoho
  • 896
  • 1
  • 7
  • 25
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
  • And this is why `.indices` exists, and why you should seldom write `0.. – Alexander May 26 '19 at 15:27
  • @Alexander i'm clarifying reason of the crash , no need for `Random` / `indices` at alll , `randomElemnt` will do the job – Shehata Gamal May 26 '19 at 15:58
  • Yep, although in some cases you need a random index (such as for setting an element, not retrieving), for which `a.indices.randomElement()` can be useful. – Alexander May 26 '19 at 16:18