Search code examples
netlogo

NetLogo: getting randomly chosen position of a repeated value in a list


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.


Solution

  • 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