1

I have an array of strings. And also I have variable that randomly chooses one string from it. The problem is – it can repeat values and I don't want that. Every value should be displayed only once. So how would I do that? I know that sets is more appropriate in this case than arrays, but it's more complicated for me

var questions = ["red", "blue", "green", "square", "tasty"]

let randomFact = Int(arc4random_uniform(UInt32(questions.count)))    

For the purpose of my app it should display new value when button is touched. I tried to remove value from array to avoid it's repeating with

questions.removeAtIndex(Int(questions[randomFact])!)

But it crashes.

So how to display every value randomly but only once?

Burundanga
  • 668
  • 5
  • 15

2 Answers2

1

I like your approach of removing the element after it's chosen. You just have a small issue with your code:

let fact = questions[randomFact]
questions.removeAtIndex(randomFact)
trojanfoe
  • 120,358
  • 21
  • 212
  • 242
  • Can you show me how to roughly do that? I tried to remove it with code above, and it crashed on me. What do you mean with current size? How many items there are left? – Burundanga Nov 10 '15 at 08:22
  • @Burundanga I have modified my answer after reading the whole of your question and seeing that you have already considered this approach. – trojanfoe Nov 10 '15 at 08:23
1

If you are performing the removal of the element while you are iterating over the length of the array, this may cause your app to crash (unless you use a removal-safe loop).

Please refer to this SO question for more information on removal-safe iterations.

EDIT 01: Loop solution

The following code works for me, does it accomplish what you are seeking?

var questions = ["red", "blue", "green", "square", "tasty"]

repeat
{
   let randomFact = Int(arc4random_uniform(UInt32(questions.count)))
   print( questions[randomFact] )
   questions.removeAtIndex(randomFact)
}while( questions.count > 0 );

This is the output:

square
tasty
green
red
blue

EDIT 02: General solution

In general, you can remove an element from an array like this:

let randomFact = Int(arc4random_uniform(UInt32(questions.count)))
questions.removeAtIndex(randomFact)

but remember, if you are somehow dependent on the initial size of the array in your code, it will cause your app to crash.

Community
  • 1
  • 1
INElutTabile
  • 866
  • 2
  • 20
  • 38
  • You can see in the question that the OP is not iterating over the array. He generates a random index and uses that to access/remove the element. – trojanfoe Nov 10 '15 at 09:08
  • The question states that @Burnundanga want to show every value in the array only once, picked randomly. I think that using a loop is inevitable, even if the loop itself is not shown in the code. – INElutTabile Nov 10 '15 at 09:12
  • No, that's an assumption on your part. He does not state that he uses iteration, only that each string element must be displayed only once. If he's "displaying" then it's more likely each element is chosen slowly allowing the value to be seen. That's not something that implies iteration. – trojanfoe Nov 10 '15 at 09:15
  • Oh, so for "displaying the value" you are happy that `print()` is enough? How does the user see that then? – trojanfoe Nov 10 '15 at 09:26
  • I have no visibility on the full code of the App, so, with a little bit of wit, you can understand that the "display" part of the app (that we cannot see) shall replace my simple "print" function. – INElutTabile Nov 10 '15 at 09:29
  • So I am without wit because I assume by "display" the OP means "display in the UI"? – trojanfoe Nov 10 '15 at 09:30
  • 1
    The display part of the App is off topic in this question ("How to access every value of array only once"), @Burnundanga asked about accessing the value of an array only once. My answer exclusevely addresses that. This discussion is going nowhere. – INElutTabile Nov 10 '15 at 09:37
  • Your answer is based on the premise that he's modifying an array that is being iterated, even though the reason for the crash is shown clearly in the question: `questions.removeAtIndex(Int(questions[randomFact])!)`. I have stated that I don't believe it's the iteration that is the problem given "Every value should be displayed only once" and if the OP was using a loop to update (say) a text field then he wouldn't see every value would he? He'd only see the last value. I still don't believe iteration is being used. – trojanfoe Nov 10 '15 at 09:40