2

I'm trying to create random test answers. Using a unique ID (Text) - Below randomizes the list only once when I use it. If I reload page it doesn't randomize again.

Also - if it is a True False Answer of only 2 choices. It doesn't work.

Any thoughts folks? Or is there an easier way to do this. I know I can do it with numbers easily, but I have a preference for unique answer ID in text)

      <cfset strList = "rttt,ddde,ffss,gggd" /> - works only once

      <cfset strList = "True,False" /> - doesn't work

      <!---
     Create a struct to hold the list of selected numbers. Because
     structs are indexed by key, it will allow us to not select
     duplicate values.
      --->

     <cfset objSelections = {} />

      <!--- Now, all we have to do is pick random numbers until our
     struct count is the desired size (4 in this demo).
      --->

      <cfloop condition="(StructCount( objSelections ) LT 4)">

     <!--- Select a random list index. --->
     <cfset intIndex = RandRange( 1, ListLen( strList ) ) />

     <!---
        Add the random item to our collection. If we have
        already picked this number, then it will simply
        overwrite the previous and the StructCount() will
        not be changed.
     --->
     <cfset objSelections[ ListGetAt( strList, intIndex ) ] = true />

      </cfloop>

      <cfoutput>
      <!--- Output the list collection. --->
      <cfset newlist = "#StructKeyList( objSelections )#">

      #newlist#

      </cfoutput>
Merle_the_Pearl
  • 1,391
  • 3
  • 18
  • 25
  • can you give an example of what the desired output would be? As an aside, you doing variable manipuation, you may want to use cfscript syntax. – James A Mohler Oct 13 '18 at 21:02
  • Your intention isn't clear to me. What should the result look like? Is `newlist` supposed to be a randomized list of `strList`? And for your two choices: Do you still expect 4 "answers" or just 2 "answers"? – Alex Oct 13 '18 at 21:02
  • Alex - I just used newlist for my varibles to use next. Its the same as strlist. As for what I'm doing. It seems to work. But when I reload the page it doesn't change things any different. So it seems to mix it up once, which is what I want. But on the reload, it doesn't do it again. Makes me think its not quite right. And if it is only 2 variables like true/false... It doesn't work. But I'm going to try work on that. – Merle_the_Pearl Oct 14 '18 at 04:31
  • So this works for 2 answers (True/False), 3 answers (A,B,C) or 4 answers (A,B,C,D) : but it only seems to mix it once and keep the same results on a reload. – Merle_the_Pearl Oct 14 '18 at 04:45
  • ListLen is easy fix for number of answers : then change cfloop and will now work for whatever ListLen is. 2,3,4,5,6 answers.. – Merle_the_Pearl Oct 14 '18 at 05:06
  • One thing to be cautious about here is that _theoretically_ you could enter a near infinite loop (especially with a large number of choices) if your random selection continues to be one that is already in your final struct. You could potentially do significantly more loops than there are elements in your input list. – Shawn Oct 15 '18 at 16:06
  • Before I forget, I threw together a demo of how building up the struct through loops can result in a lot of extra looping. And the difference in time between looping and Java shuffling. Run multiple times to see how the iterations can change with looping. https://trycf.com/gist/cce39c3921d5d2541962b143ba9ed76c/acf?theme=monokai – Shawn Oct 15 '18 at 19:45

2 Answers2

1

If you are looking to return a randomized list of answers, you can use Java Collections to interact with your ColdFusion list (after turning the list into an array).

<cfscript>
  // Our original answer list.
  strlist1 = "rttt,ddde,ffss,gggd" ;

  // Convert our lists to arrays. 
  answerArray1 = ListToArray(strList1) ;

  // Create the Java Collection object. 
  C = CreateObject( "java", "java.util.Collections" ) ;

  // Java shuffle() our array.
  C.shuffle(answerArray1) ;

  // Output our shuffled array (as an array).
  writeDump(answerArray3) ;
  // Or convert it to a list for output.
  randomAnswerList = ArrayToList(answerArray3) ;
  writeoutput(randomAnswerList) ;
</cfscript>

https://trycf.com/gist/3a1157a11154575e705411814d10ea92/acf?theme=monokai

Since you're working with small lists, Java's shuffle() should be pretty quick. With large lists, I believe it can be much more inefficient than building out a randomizing function to shuffle the list. This works because ColdFusion Arrays are automatically also Java Arrays. CF works very well with Java, especially for these types of manipulations.

Note 1: Java shuffle() operates directly on its input array, so you are actually changing the array itself.

Note 2: Depending on what you want to do with the list, it may be much easier to leave your shuffled answers in an Array object and work with that. Also, Java Collection.shuffle() will work with Structs. And are you generating the answer list from a query? This will still work, but depending on how you use the query afterwards, you probably wouldn't want to use shuffle() directly on the query object.

Shawn
  • 4,758
  • 1
  • 20
  • 29
0

The reason it does not re-randomize your list after a reload is because Structs are not ordered. You are better to use an array or even a java hashtable. If I understand correctly, you are just trying to take a list, and output a re-ordered version of the list? It's probably been answered before in more suscint forms than this, but here is a way, if I have understood your requirement correctly:

<cfset strList = "rttt,ddde,ffss,gggd" />

<cfset newlist = "">
<cfloop condition="ListLen(strList)">
    <cfset intIndex = RandRange( 1, ListLen( strList ) ) />
    <cfset newlist = ListAppend(newlist, ListGetAt(strList, intIndex))>
    <cfset strList = ListDeleteAt(strList, intIndex)>
</cfloop>

<cfoutput>#newlist#</cfoutput>
  • If any of your answers have commas in them, then this would cause a problem. To solve that, you can add a different way to delimit between answers (like maybe three pipes '|||') in the 5 list functions. – drew sutherland Oct 15 '18 at 10:06
  • Works perfect! All question randomized. The answers are not included in the UniqueID, so no problems with that. They are populated after the randomization. – Merle_the_Pearl Oct 15 '18 at 18:37