If I have the following: set list [8 1 0 3 4 2 0 1 2 4 25 0 3 3]
. I would like to find a way to get, for example, a random item position for zero (2, 6 or 11) or for three (3, 12 or 13).
I have tried with:
let i (position (one-of list = 0) list )
print i
However, that only returns a boolean i
. I know I could use position 0 list
, but that gives priority to the first position (2, in the case of zero) while I would like it to randomly chosen from all values equal to zero on the list. I thought of using a while[]
, but I was wondering if there is a faster and simpler way.
In general, when you are working with lists, it is a good idea to familiarise yourself with anonymous procedures and some related primitives like map
and filter
.
I wrote a quick procedure, called positions
that should be able to take care of this. First I create a list containing all the possible indexes: index-list
.
Next, I use map
to simultaneously go through the input-list
and the index-list
. It uses ifelse-value
to check for each item of the input-list
whether or not it corresponds to the input-item
that you wanted to check it against. If they correspond, it returns the position of that item in the input-list. Otherwise it returns FALSE.
The final step is to filter
out all the FALSE responses so that you are left with a list containing only the positions of your input-item
in the input-list
.
to-report positions [ input-item input-list ]
let index-list range length input-list
let position-list (map [ [list-item index] -> ifelse-value input-item = list-item [index][FALSE] ] input-list index-list)
report filter [index -> index != FALSE] position-list
end
Testing this gives [2 6 11]
as a result, which corresponds with what you would expect
to test
let my-list [8 1 0 3 4 2 0 1 2 4 25 0 3 3]
show positions 0 my-list ;[2 6 11]
end