Selecting items randoms from a list

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
PuzzledGreatly
Posts: 1303
Joined: 29 Sep 2013, 22:18

Selecting items randoms from a list

06 Nov 2013, 09:28

What's the most efficient method to select a given number of items randomly from a list so that no item is selected more than once. I'm currently using the following:

Code: Select all

	
Total = 30 ;for example
nUp = 6 ; for example select 6 items
t = 1
	While t <= nUP
	{		
		Retry:
		Random, Ran, 1, %Total%
		if Ran <> TargN
		if Ran not in %numbers%
		numbers = %numbers%%Ran%,
		else
		goto Retry
		t ++		
	}
msgbox %numbers%
But I think there must be a better way.
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: Selecting items randoms from a list

06 Nov 2013, 09:53

Just a shorter one:

Code: Select all

Total := 30 ; for example
nUp   := 6  ; for example select 6 items
t     := 1

While t <= nUP
{
	Random, Ran, 1, %Total%
	if Ran not in %numbers%
		numbers .= Ran ",", t ++
}

MsgBox %numbers%
Verdlin
Posts: 63
Joined: 04 Oct 2013, 08:55
Contact:

Re: Selecting items randoms from a list

06 Nov 2013, 10:08

t isn't even necessary. A_Index works fine

Code: Select all

Total := 30 ; for example
nUp   := 6  ; for example select 6 items

While (A_Index <= nUP)
{
    Random, Ran, 1, %Total%
    if Ran not in %numbers%
        numbers .= Ran ",", (A_Index) ; A_Index is faster when forced to an expression, i.e. (A_Index)
}

MsgBox %numbers%
User avatar
LinearSpoon
Posts: 156
Joined: 29 Sep 2013, 22:55

Re: Selecting items randoms from a list

06 Nov 2013, 15:27

It is necessary actually. A_Index still increments even if the random number chosen was picked in a prior loop iteration. It could be removed with a second loop I suppose...but that's probably more work than it saves.

Also, since you have a comma on that line... your entire expression is just this:

Code: Select all

(A_Index)
...which doesn't really do anything to begin with.
User avatar
PuzzledGreatly
Posts: 1303
Joined: 29 Sep 2013, 22:18

Re: Selecting items randoms from a list

06 Nov 2013, 22:56

Thanks, tmplinshi, that's much neater than my original method.
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: Selecting items randoms from a list

06 Nov 2013, 23:41

Code: Select all

#NoEnv
SetBatchLines, -1
Total := 300000
nUp   := 60000
t     := 1
n     := {}


Tick := A_TickCount
While t <= nUP
{
    Random, Ran, 1, %Total%
    if (!n[Ran])
        n[Ran] := 1, t++, numbers .= Ran ","
}
MsgBox, % A_TickCount - Tick "ms.`n" numbers


t     := 1
numbers := ""
Tick := A_TickCount
While t <= nUP
{
    Random, Ran, 1, %Total%
    if Ran not in %numbers%
        numbers .= Ran ",", t ++
}
MsgBox, % A_TickCount - Tick "ms.`n" numbers
User avatar
empardopo
Posts: 336
Joined: 06 Oct 2013, 12:50
Location: Spain
Contact:

Re: Selecting items randoms from a list

07 Nov 2013, 03:47

Verdlin wrote:t isn't even necessary. A_Index works fine

Code: Select all

Total := 30 ; for example
nUp   := 6  ; for example select 6 items

While (A_Index <= nUP)
{
    Random, Ran, 1, %Total%
    if Ran not in %numbers%
        numbers .= Ran ",", (A_Index) ; A_Index is faster when forced to an expression, i.e. (A_Index)
}

MsgBox %numbers%
Using this code, I get this

Image

Is this correct? I only get five numbers. Other times I got four.

However, running this code

Code: Select all

Total := 30 ; for example
nUp   := 6  ; for example select 6 items
t     := 1

While t <= nUP
{
    Random, Ran, 1, %Total%
    if Ran not in %numbers%
        numbers .= Ran ",", t ++
}

MsgBox %numbers%
I always get six numbers.

Greetings!
Everything is possible!
User avatar
dmg
Posts: 287
Joined: 02 Oct 2013, 01:43
Location: "Twelve days north of Hopeless and a few degrees south of Freezing to Death"
Contact:

Re: Selecting items randoms from a list

07 Nov 2013, 05:48

One reliable and relatively efficient way to randomly shuffle a list with no repeats is to use the Fisher-Yates Shuffle:

Code: Select all

msgbox, % _shuffle("abcdefghijklmnopqrstuvwxyz")
msgbox, % _shuffle("one two buckle my shoe", " ")
msgbox, % _shuffle("three|four|close|the|door", "|")

_shuffle(input, delimiter = "")
 {
   delimiter := (!instr(input, substr(delimiter, 1, 1)) ? "" : substr(delimiter, 1, 1))
   array := {}
   loop, parse, input, %delimiter%
    {
      array.insert(a_loopfield)
    }
   while, array.maxindex()
    {
      random, ran, 1, array.maxindex()
      shuffled .= delimiter . array[ran]
      array.remove(ran)
    }
   return ltrim(shuffled, delimiter)
 }
You could also just use the random parameter of the Sort command.
http://en.wikipedia.org/wiki/Fisher%E2% ... es_shuffle
"My dear Mr Gyrth, I am never more serious than when I am joking."
~Albert Campion
------------------------------------------------------------------------
Website | Demo scripts | Blog | External contact
User avatar
empardopo
Posts: 336
Joined: 06 Oct 2013, 12:50
Location: Spain
Contact:

Re: Selecting items randoms from a list

07 Nov 2013, 08:46

Is It possible to get only 3 elements using _shuffle function?

msgbox, % _shuffle("abcdefghijklmnopqrstuvwxyz",3)

And get for example, a m and z...

Greetings!
Everything is possible!
User avatar
sinkfaze
Posts: 616
Joined: 01 Oct 2013, 08:01

Re: Selecting items randoms from a list

07 Nov 2013, 17:12

For the OP:

Code: Select all

total := 30, nUp := 6
 , n := numbers :=	""
Loop
	n .=	A_Index ","
Until	(A_Index=total)
Total :=	SubStr(Total,1,StrLen(Total)-1)
Sort, n, Random D`,
Loop, parse, n, `,
	numbers .=	A_LoopField ","
Until	(A_Index=nUp)
numbers :=	SubStr(numbers,1,StrLen(numbers)-1)
MsgBox %numbers%
User avatar
PuzzledGreatly
Posts: 1303
Joined: 29 Sep 2013, 22:18

Re: Selecting items randoms from a list

10 Nov 2013, 10:21

Thanks for the replies. Now I'm wondering what the best method is to pull one or more chosen items with a given number of random items.
User avatar
AfterLemon
Posts: 85
Joined: 30 Sep 2013, 14:27
Location: Ohio, USA

Re: Selecting items randoms from a list

14 Nov 2013, 15:20

Accepted Inputs:
Var Containing Comma-Delimited Strings
Array*
Max Number

To output an amount of random numbers using 1-%Max% (inclusive) use:
Msgbox,% RandItems(10,,30)

To output array with an amount of randomized elements from another array use something like:
Arr:=["blah","ahh","har","arrh","barr","bahh","rabb","arbb","harb","brah","rabh","arrh","arrr","rahh","raaa","baaa","haaa"]

Msgbox,% st_Printarr(RandItems(10,,Arr*))


To output string with an amount of random elements from another array use:
MsgBox,% (RandItems(10,1,Arr*)

Code: Select all

	
RandItems(NumOut,StringOut:=0,ArrOrMaxNum*){
	t:=1,O:=[]
	If((ArrOrMaxNum[1]&1!="")&&!(ArrOrMaxNum.MaxIndex()>1)){
		While(ArrOrMaxNum[1]--?1:(0,n:=SubStr(n,1,-1)))
			n.=A_Index	","
	}else If(ArrOrMaxNum.MaxIndex()>1){
		I:=ArrOrMaxNum.MaxIndex()
		While(I--?1:(0,n:=SubStr(n,1,-1)))
			n.=ArrOrMaxNum[A_Index] ","
	}else n:=ArrOrMaxNum[1]
	Sort,n,Random D`,
	Loop,parse,n,`,
		(StringOut?O.=A_LoopField	",":O[t].=A_LoopField),t++
	Until T=NumOut+1
return (O.HasKey(O.MaxIndex())?O:RTrim(O,","))
}
;==============================
st_printArr(array, depth:=5, indentLevel:="")
{
	for k,v in Array
		list.=indentLevel "[" k "]",((IsObject(v)&&depth>1)?(list.="`n" st_printArr(v,depth-1,indentLevel " 	")):list.=" => " v),list.="`n"
	return rtrim(list)
}
Note: st_PrintArr function is ONLY used to show contents of the output array.
User avatar
FanaticGuru
Posts: 1908
Joined: 30 Sep 2013, 22:25

Re: Selecting items randoms from a list

14 Nov 2013, 19:12

If you are truly wanting a number of random items from a list and not just non-repeating random numbers you can do this:

Code: Select all

List = 
(Join`n
apple
banana
grape
pear
pineapple
)

X := 3

Sort, List, Random

MsgBox % SubStr(List,1,InStr(List,"`n",1,1,x))
FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: peter_ahk and 330 guests