Netlogo, Mapping one to one over two lists - netlogo

I want to find out how to map one to one from two lists. Where length of both the lists are the same.
For Example,
list A = [turtle-0 turtle-3 turtle-5]
list B = [Node-27 node-21 node-29]
I want to map,
turtle-0 to node-27
turtle-3 to node-21
turtle-5 to node-29
and store each of the nodes in turtle-own variable called travel-to.
I have feeling you can achieve this the map or foreach functions, but unfortunately I haven't been successful. Any ideas, Thanks

Using indices, as in geruter's answer, will work, but isn't necessary.
Both map and foreach let you process multiple lists by surrounding the whole call in parentheses, so for example:
observer> show (map [[?a ?b] -> word ?a ?b] [1 2 3] ["a" "b" "c"])
observer: ["1a" "2b" "3c"]
or, shorthand syntax,
observer> show (map word [1 2 3] ["a" "b" "c"])
observer: ["1a" "2b" "3c"]
re:
I have feeling you can achieve this the map or foreach functions, but unfortunately I haven't been successful.
It would help us help you if you showed us your best attempt, and described where you got stuck (was there an error message? incorrect behavior?).

Maybe the pros here will come up with a better solution, but the code below should work.
Actually you could use foreach or map, both return the same results.
The 2 report functions below work for lists, not quiet sure of the also will work with agentsets.
to test
let list1 [1 2 3 4 5 6]
let list2 ["a" "b" "c" "d" "e" "f"]
show foreach-2-lists list1 list2
show map-2-lists list1 list2
end
to-report foreach-2-lists [list1 list2]
let result []
if length list1 != length list2 [ report "Error" ]
let index range length list1
foreach index [ i ->
set result lput ( list ( item i list1 ) ( item i list2 ) ) result
]
report result
end
to-report map-2-lists [list1 list2]
if length list1 != length list2 [ report "Error" ]
let index range length list1
let result map [ i -> ( list ( item i list1 ) ( item i list2 ) ) ] index
report result
end
test will return you the result of both functions:
observer> test
observer: [[1 "a"] [2 "b"] [3 "c"] [4 "d"] [5 "e"] [6 "f"]]
observer: [[1 "a"] [2 "b"] [3 "c"] [4 "d"] [5 "e"] [6 "f"]]

See below for a version using foreach. The trick is to access the two lists through parallel iteration. This won't work with map because you are wanting to do a command (that is, change things) rather than a reporter (extract information).
turtles-own [ my-destination ]
to testme
clear-all
; set up test data lists
create-turtles 5
let agents shuffle sort-on [who] n-of 3 turtles
print agents
let destinations (list "A" (one-of patches) 33 )
print destinations
; do the matching with foreach
let indices range length agents
foreach indices
[ idx ->
ask item idx agents
[ set my-destination item idx destinations
]
]
ask turtles [ show my-destination ]
end

Related

How to access individual values ​of a list item in NetLogo 6.2?

I'm not able to assign the first item value of a list to a turtle variable. For example? I have list3 that has 1 item, that is:
list3: [[5 2]]
I would like the first value of list 3 item 0 to be assigned to reproduction (ie 5) and the second value of list 3 item 0 to be assigned to metabolism (ie 2).
How can I do this?
Thanks in advance
globals [ ValidHabsItem ValidHabs ItemList3 ]
turtles-own [ profiles-habitat metabolism reproduction ]
to setup
let list1 ( list 2 )
let list2 ( list 5 )
let list3 ( reduce sentence ( map [ i -> map [ j -> list j i ] list2 ] list1 ) )
print ( word "list3: " list3 )
let n0 count turtles
let s length list3 * 10
while [ n0 < s ]
[
let c count patches
if c = 0 [ stop ]
ask one-of patches
[
sprout 1
[
set profiles-habitat item ValidHabsItem ValidHabs
set reproduction item ItemList3 list3 ;; list3: [[5 2]];; value 5
set metabolism item ItemList3 list3 ;; list3: [[5 2]];; value 2
]
]
]
set n0 count turtles
end
You can easily understand how to do this by playing in the Command Center and seeing how NetLogo responds to your calls to the list.
Just create a global variable in the Code tab, as globals [my-list], and then follow my statements in the Command Center:
observer> set my-list [[1 2 3] [4 5 6] [7 8 9]]
observer> print my-list
[[1 2 3] [4 5 6] [7 8 9]]
So here we just created a list whose items are other lists.
Therefore, we have:
observer> print first my-list
[1 2 3]
observer> print last my-list
[7 8 9]
observer> print item 1 my-list
[4 5 6]
This means that now, for NetLogo, the whole first my-list statement is equal to [1 2 3]; in other words, it is a list containing those numbers. So you can treat first my-list as any other list. For example, if you want to extract the second item from that list, you will simply do:
observer> print item 1 (first my-list)
2
The parentheses there are optional: they are useful to make the statement more readable to humans, reminding us that the whole first my-list is a list from which we are extracting the second item (i.e. the item with index 1). However, NetLogo does not really need that:
observer> print item 1 first my-list
2
Now you should be able to easily solve your problem, because your case is easier than this: your list3, which in your example is [[5 2]], only has one item in it. This means that first list3 is equal to last list3 which is equal to item 0 list3, all of them being [5 2].
So there you can do:
set reproduction first (first list3)
set metabolism last (first list3)
In general, you can apply this mechanisms to how many levels of nesting you wish.
For example:
observer> set my-list [[[1 2] [3 4]] [[5 6] [7 8]]]
observer> print my-list
[[[1 2] [3 4]] [[5 6] [7 8]]]
observer> print first my-list
[[1 2] [3 4]]
observer> print last (first my-list)
[3 4]
observer> print first (last (first my-list))
3
PS:
Note that, in your while loop, you need to include set n0 count turtles within the command block (as in while [condition] [commands]).
The way you have it now, set n0 count turtles is outside the command block of the loop and this means that the loop will go on forever, because it will never get to the point where n0 is updated and so n0 < s will always evaluate as true.
Also, note that saying
let c count patches
if c = 0 [ stop ]
makes no sense in NetLogo: every model will always have at least one patch, so you will never get to the point of having no patches.
Maybe you wanted to say something like if (count patches with [not any? turtles-here] = 0) [stop]? Just guessing, but here we are going off-topic

How to select the last n items from a list in Netlogo

I would need to store a removed item from a list (list 1) into a new one (list 2) and select the last n items from this list. Lists' maximum length is 10, but there could be less items stored there.
Items are stored using fput, so they are from the newest to the oldest.
To remove the oldest item, that I would like to add into the list 2, I am using the following lines of code:
if length list_1 > 10 [
set list_1 but-last list_1 print "The item is removed"
]
and I would like to add this item into list_2. Once I have more than 3 items in the list_2, I would like to select n (e.g. 1) of the last items added to it.
Do you have any idea on how I can do that?
Thanks in advance for your help.
I think sublist is probably easiest here- use it to subset from your n-index, as "length of the list - n", to the length of your list.
globals [ list1 list2 ]
to setup
ca
set list1 ( range 1 11 )
set list2 []
reset-ticks
end
to go
let n 3
print ( word "List 1:\n" list1 "\n" )
if not empty? list1 [
set list2 lput last list1 list2
set list1 but-last list1
]
if length list2 > 3 [
let list2Sublist sublist list2 ( length list2 - n ) ( length list2 )
print ( word "List 2 sublist:\n" list2Sublist "\n" )
]
tick
end
Hopefully that gets you in the right direction!

Netlogo: Obtaining a third list from the relation of other two lists

I want to extract a third list from the relation of two previous lists. Here is the example:
I have a process in NetLogo that outputs a list of 0 and 1, let's call it List_A:
let List_A [0 1 0 1 1 ]
The positions of 0 and 1 always vary depending on several factors that are not relevant to this question.
There is a second list related to List_A called List_B:
let List_B [“residential” “industrial” “commercial” “farmland” “preservation”]
The positions of this list items never vary.
The third list I want to obtain is items of List_B that have a position corresponding to positions in items of List_A that have a value of 1. So, according to the previous examples, this would be a list made of [“industrial” “farmland” “preservation”], because “residential” and and “commercial” would have position that corresponds to a value of 0 and thus removed from the list.
Made some progress with this code that outputs a list of the positions of List_A of items that have value 1:
to-report comp-positions
report filter [ i -> item i List_A = 1 ]
n-values (length List_A) [ i -> i ]
end
but don’t know how to apply it to List_B to obtain the third list.
For completeness, three more ways:
print map last filter [ p -> first p = 1 ] (map list List_A List_B)
print reduce sentence (map [ [a b] -> item a (list [] b) ] List_A List_B)
print reduce [ [acc val] ->
ifelse-value (first val = 1) [ lput last val acc ] [ acc ]
] fput [] (map list List_A List_B)
There is probably a one-step way, but maybe use a combination of map and filter? A map using ifelse-value can produce a list of the zeroes and "List_B" items, then filter to drop the zeroes:
to filter-map
let List_A [0 1 0 1 1 ]
let List_B [ "residential" "industrial" "commercial" "farmland" "preservation"]
print filter [ i -> i != 0 ] ( map [ [ a b ] -> ifelse-value (a = 1) [b] [0] ] List_A List_B)
end

Changing filtered values in a nested list

I have a nested list, in which each sublist is structured as follows: [[xcor ycor] weight].
Each tick I'd like to update the weight in a sample of these sublists.
I produce the sample (e.g. of size 2) from the nested list total using the Rnd extension (and very helpful answers/comments):
set total [ [[0 1] 1] [[2 3] 2] [[4 5] 3] [[6 7] 4] [[0 1] 1] ]
set sample rnd:weighted-n-of 2 total [ last ? ]
Then I update the weights in the sample (let's say multiplying them by 2) and map them to their respective [xcor ycor]-pair.
let newWeights (map [last ? * 2] sample)
let updatedSample (map list (map [first ?] sample) newWeights)
How can I then replace those entries in total, bearing in mind that it may hold duplicate entries?
This seems to be the perfect job for replace-item, but I don't know how to construct an appropriate index and then pass the respective value from updatedSample.
This is a great problem. The data structure you're using is known as an association list, or alist for short, where the keys are [xcor ycor] and the values are weights. Given your task, it's better to use the keys to look things up rather than indices. Thus, replace-item doesn't really help here. Instead, we can run map on total, using the values from updatedSample if they're there, and defaulting to the values in total. First, we need a convenience function to look things up in the alists. In lisp (a language which influenced NetLogo), this is called assoc. Here it is:
to-report assoc [ key alist ]
foreach alist [ if key = (first ?) [ report ? ] ]
report false
end
Notice that false is returned if alist doesn't contain the key. We want to use the entry returned by this function if it's not false, otherwise use something else. Thus, we need another helper function:
to-report value-or-else [ value default ]
report ifelse-value (value = false) [ default ] [ value ]
end
Finally, we can write a function that does the mapping:
to-report update-alist [ alist updated-entries ]
report map [ value-or-else (assoc first ? updated-entries) ? ] alist
end
Here's it in action:
observer> show update-alist [[[0 1] 1] [[2 3] 2] [[4 5] 3] [[6 7] 4] [[0 1] 1]] [[[0 1] 10] [[4 5] 45]]
observer: [[[0 1] 10] [[2 3] 2] [[4 5] 45] [[6 7] 4] [[0 1] 10]]
You would want to call it like update-alist total updatedSample.

NetLogo : How to do multiple operations on lists (find, get , replace, remove , search elements within lists , ....)

I am new to NetLogo and I was wondering if there is a complete reference to do operations on lists, I have read most of the posts here in addition to Netlogo dictionary but for example if I need a list of pairs of numbers like
[[1 2] [2 2] [2 3] ,,, ]
when I search
member? 3 thislist
Will I have the option to say which element of inner list I am considering for the search ? for instance I will get false if it search first element and true if I search second element.
Can anybody please clarify the use of lists in Netlogo?
map, filter, reduce, foreach, n-values, and sort-by provide customizable operations on lists, using tasks. See http://ccl.northwestern.edu/netlogo/docs/programming.html#tasks.
Here's your example using map:
observer> show member? 3 map first [[1 2] [2 2] [2 3]]
observer: false
observer> show member? 3 map last [[1 2] [2 2] [2 3]]
observer: true
It appears Seth answered your initial question. To answer your follow up question on changing an item, you can use replace-item See: http://ccl.northwestern.edu/netlogo/docs/dictionary.html#listsgroup
or use map. Below is an example replacing the first item with a -99 if the second item is 3:
let aList [[1 2] [2 2] [2 3] [4 4] [5 3]]
set aList map [(list ifelse-value (item 1 ? = 3) [-99][item 0 ?] item 1 ?)] aList