Hello,
I am trying to randomly sample x amount of rows from a CDT by generating x random numbers in the range 1:length(myCdt). The issue I am getting is that some of these random numbers are repeated.
Is there a way to generate random numbers in a given interval and have them be unique?
Here is what I have so far:
local!randomNumbers:if(
length(local!query)>15, 1+ tointeger(rand(15) * length(local!query)), local!query,
),
Discussion posts and replies are publicly visible
community.appian.com/.../generating-uuids-guids
Without using a recursive approach, this is tricky. The most simple approach might be, to just generate more numbers, get the unique ones and then take the first few. Find a code example below.
index( union(tointeger(rand(100)*50), tointeger({})), enumerate(15) + 1, {} )
I see, is there a limit to how high that number should be?
Hm... as this is random, it could, in theory, generate a thousand times the same number. In practice, you could double it.
In my tests, when generating 50 numbers, I had 0-3 double. When you need 15, you should be good with 20. If your application breaks, in case you only show 13 or 14 items, go a bit higher.
a!localVariable( local!possibleNumbers: difference( 1+enumerate(ri!upper), 1 + enumerate(ri!lower) ), local!count: length(local!possibleNumbers), local!randomIndex: tointeger(local!count*(rand())), if(local!randomIndex =0, local!possibleNumbers[tointeger(local!count*(rand()))], local!possibleNumbers[local!randomIndex] ) )
Your code generates a single random number between two boundaries. A more simple variant is
ri!lower + tointeger(rand() * (ri!upper - ri!lower))
Thanks for the advice, any way this could be used to generated x amount of numbers that are all unique?
Makes sense, I think using a multiple of the length of my cdt might be a good way of choosing that limit
There might be a simpler way to do this, but this solution should guarantee a random order without repeated data regardless of how many values you have:
a!localVariables( local!numberOfValues: 15, local!randomData: rand(local!numberOfValues), local!index: a!forEach( items: local!randomData, expression: rank( fv!item, local!randomData ) ), index( enumerate(local!numberOfValues)+1, local!index ) )
Basically you just generate a list of random decimals and then find the rank in the list of each of them. That will guarantee that all values are used and that they don't repeat!
here is the recursive approach for getting x amount of unique numbers between a define range
a!localVariables( local!random: ri!min + tointeger(rand() * (ri!max - ri!min)), local!arrray: append(ri!array, local!random), if( length(union(local!arrray, local!arrray)) >= ri!count, local!arrray, rule!CP_getRandomList( min: ri!min, max: ri!max, count: ri!count, array: union(local!arrray, local!arrray) ) ) ) // NOTE - count < max - min
more insights ->