roman
roman

Reputation: 33

Take random item from list in "for" loop

I have a list containing a random element from another list
var test = listOf<String>("Blah blah " + list1.shuffled().take(1)[0] + " blah blah")
A bigger list biglist, containing a smaller lists like test
Then, there is a "for" loop, in which I am filling stringbuilder with random lists from biglist

    var list3 = listOf<String>("Something something1","Something something2")
    var list2 = listOf<String>("item1", "item2", "item3", "item4")
    var list = listOf<String>("Blah " + list2.shuffled().take(1)[0] + " blah")
    var sb = StringBuilder ()
    var biglist = listOf<String>()
    if (...) biglist += list
    if (...) biglist += list3.get(0)
    if (...) biglist += list3.get(1)
    for (i in 0 until 4) {
        sb.append(biglist.shuffled().take(1)[0] + "\n")
        i + 1
    }
    
    println(sb)

So, on output, I want to see something like this:

Something something1
Blah item2 blah
Something something2
Blah item4 blah

Instead I am having this:

Something something1
Blah item2 blah
Something something2
Blah item2 blah

My problem is, that in sb, test list will every time contain the same item, randomly picked at the beginning of code from list1
I have kind of solved it, putting creation of the biglist INTO the for loop (and clearing it after sb.append), but it just make my code looks even shittier (and slower?)

Maybe there is a better solution to this? Thanks

Upvotes: 1

Views: 486

Answers (1)

Willi Mentzel
Willi Mentzel

Reputation: 29864

Do your evaluation of list inside the loop:

var list3 = listOf("Something something1", "Something something2")
var list2 = listOf("item1", "item2", "item3", "item4")

var sb = StringBuilder()

(0..4).forEach {
    var list = listOf("Blah ${list2.shuffled().first()} blah")

    var biglist = listOf<String>()
    biglist += list // left out the if statements for simplicity
    biglist += list3.get(0)
    biglist += list3.get(1)
    sb.append(biglist.shuffled().first() + "\n")
}

println(sb)

A few notes:

  • use a range and forEach to do it multiple times (since you don't need the loop variable i anyways
  • take(1)[0] can be replaced by first()
  • use a string template to build the element of list
  • you don't need the type parameter for list2 and list3, the type (String) can be inferred from the list's elements
  • if your list becomes big calling shuffle will be a waste of resources, especially because you are only interested in one random element of that list. Use this extension function instead: fun List<*>.randomElement() = this[Random().nextInt(this.size)]

Upvotes: 1

Related Questions