Non-repetitive Random Selection of items from a list
Here, I described how you can make a random selection from a list of items … but there are times when you need to make such random selections without repeating any of the selections … this article details how you would go about implementing this with VisualNEO for Windows.
In your App’s StartUp section … code something like this …
SetVar "[myInitialFruits]" "!/Apple,/Banana,/Cherry,/Pear,/Peach,"
SetVar "[myFruits]" "[myInitialFruits]"
Note that each item has a prefix and a suffix character surrounding it ; without the prefix character, it would be difficult to differentiate between items like “NEO” and “VisualNEO” and “VisualNEO Win”
If the items in your list contain a comma or forward slash, you can use different characters to separate the items … e.g. a dollar sign and a semicolon … or even multi-character separators like @#$%.
The StrParse command will create an arrayed variable set from the (comma) separated list of items … so you will end up with variables [myFruitsItem1], [myFruitsItem2] etc. … where [myFruitsItem1] will contain the value /Apple, [myFruitsItem2] will contain the value /Banana and so on.
Then, when you want to get a random item from the list …
If "[myFruits]" "=" ""
AlertBox "Sorry" "list is empty"
Return
EndIf
...
StrParse "[myFruits]" "," "[myFruitsItem]" "[myFruitsItemCount]"
If "[myFruitsItemCount]" ">" "1"
Random "[myFruitsItemCount]-1" "[RandomItemNumber]"
SetVar "[RandomItemNumber]" "[RandomItemNumber]+1"
SetVar "[NextRandomItem]" "[myFruitsItem[RandomItemNumber]]"
... remove the prefix character
StrReplace "[NextRandomItem]" "!/" "" "[NextRandomItem]"
... remove this item from the list
StrReplace "[myFruits]" "!/[NextRandomItem]," "" "[myFruits]"
Else
... one item left in list ; remove prefix and suffix characters
StrReplace "[myFruits]" "!/" "" "[myFruits]"
StrReplace "[myFruits]" "!," "" "[NextRandomItem]"
SetVar "[myFruits]" ""
EndIf
Depending on the nature of your application, instead of the AlertBox command you may choose another action … like re-load the [myFruits] list from [myInitialFuitsList]
The Random command returns a random number between 0 and the value in the first parameter … since you want a number between 1 and the number of items in the list … you ask for a result between 0 and a number that is one less than the number of items in the list … then you add one to whatever result is returned.
You then use the number returned as the index to get the corresponding array item … so if [RandomItemNumber] was 3, then [NextRandomItem] would contain /Cherry … because [myFruitsItem3] was set to this value by the StrParse command before … and the next StrReplace command will remove the prefix character of “/”.
If your applications need to make such random selections frequently, you can consider making up your own custom commands … so you can implement the same functionality with just 2 commands … something like …
Call "gkExtractListToArray" "!/Apple,/Banana,/Cherry,/Pear" "!/" "," "myFruitsItem"
… and …
If "[myFruits]" "=" ""
AlertBox "Sorry" "list is empty"
Return
EndIf
...
Call "gkExtractRandomListItem" "myFruitsItem" "!/" "," "[NextRandomItem]"
Finally, if you have lists with a lot of items … you could keep your list in a .txt file … one item per line … use something like notepad.exe to make up a file that looks like …
/Apple
/Banana
/Cherry
/Peach
… and in your pub’s StartUp section … code something like this …
FileRead "[PubDir]myFruits.txt" "All" "[myInitialFruits]"
StrReplace "[myInitialFruits]" "[#13][#10]" "," "[myFruits]"
… and if you don’t need to change the contents of such lists at run time, you could also mark the file as Embedded … and replace [PubDir]myFruits.txt above with [Embedded]myFruits.txt.
Comments