Aitor
Aitor

Reputation: 23

Find the first item in a list from the value of an attribute in Netlogo

I am working in Netlogo with a model where each agent has a path through the network. Each node has an attribute called 'mode' with values ["bike" "bus" "train" "u-g"]. I want to find the first myway item that has a different mode from the previous one. For example:

observer> ask turtle 4455 [show myway]
 
turtle 4455 > [(vertex 77445) (vertex 66227) (vertex 39816) (vertex 98972) (vertex 47091) (vertex 88001)]

The correspondence with the modes would be ["bike" "bike" "bike" "bike" "train" "train"], so I would need to find item 4, i.e. the first different mode in the list.

My attempt to solve it is to create a new list with modes for each vertex like this:

ask turtle 4455 [
let mymodes [] 
foreach myway [ r -> 
set mymodes lput [mode] of r mymodes]
show mymodes]

[ "bike" "bike" "bike" "bike" "train" "train"]

I now try to find the position of the first "train" in the list with the commands position and first:

show position (first mymodes != "Bici") mymodes

But it returns "false", and I need the position.

Upvotes: 2

Views: 52

Answers (2)

Charles
Charles

Reputation: 4208

You might try this:

let f first mymodes
let tf map [m -> (m = f)] mymodes
show position false tf

tf is a list of true/false values corresponding to whether each element of mymodes is equal to the first. position then finds the first false value.

Note that you can create mymodes with map instead of foreach:

let mymodes map [r -> [mode] of r] myway

map is a very useful primitive.

Upvotes: 3

Luke C
Luke C

Reputation: 10336

Here is one way- iterate over the positions / indices of the items in your list and use those to compare item i and item i-1. Here I've set up a reporter called report-first-different that returns the position of the first different item if one is found, and returns -1 if no difference is found (for example, if only 'bike' is present):

extensions [rnd]

to-report report-first-different [input-list]
  ; Iterate over the indices of the input-list 
  foreach range length input-list [ i ->
    ; Ignore the first item
    if i > 0 [
      ; If there is a difference between the item from current index
      ; and the item from previous index, report the current index
      if item i input-list != item (i - 1) input-list [ report i]     
    ]
  ]  
  ; If all items are the same, report -1
  report -1 
end


to show-example
  ; Set up a test list, biased towards 'bike'
  let ls [ ["bike" 5 ] ["bus" 1]  ["train" 1] ]
  let test-list map first map [ y -> rnd:weighted-one-of-list ls [ x -> last x ] ] range 8
   
  print "Test list:"
  print test-list
  
  print "Position of first different:"
  print report-first-different test-list
end

Example output:

Test list:
[bike bike bus bus bike bus train bike]
Position of first different:
2

Test list:
[bike bike bike bike bike bus bike train]
Position of first different:
5

Test list:
[bike bike bike bike bike bike bike bike]
Position of first different:
-1

Upvotes: 2

Related Questions