I noticed this instruction
set first-tens sublist mylist 0 10
causes an error if there are less than 10 elements in mylist.
How can I safely get the first 10 elements (or all the presents in mylist if there are less than 10)?
You can use ifelse-value to do this, combined with just checking the length:
set first-tens ifelse-value (length mylist < 10) [ mylist ] [ sublist mylist 0 10 ]
Related
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
I would like to make the sum = the total of pollen recieved by a plant from other plants (Donnors) which is stored in a list of a list (own by each turtle = plant).
The following code make an error (when computing the sum):
OF expected input to be an agent or agentset but got the list
[[119.05593 50 50] [301.25853 50 50] [30.23906 50 50] [460.525845 50
50] [55.16717 50 50] [301.25853 50 50]] instead.
Does any one could help me about the mistake in the line "set Tot_pol sum ..." ?
Many thanks for your help.
to check-pol [m] ;; we check the pollen recieved by the two morphs
set Donnors [] ;; empty list of pollen donnors
ask zsps with [morph = m] ;; morph of the pollen reciever
[
set totpol 0
;; check for pollen donnors and morph for compatiblity within a radius :
ask zsps with[distance myself <= 20 and morph != m]
[
set totpol (NMaleFlowers * 100 * item round (distance myself) pollination-list) ;; the farther the less pollen
set Donnors lput [ (list totpol NMaleFlowers NFemFlowers)] of myself Donnors
]
set Tot_pol sum [ item (position 0 Donnors) Donnors ] of Donnors ;; total of pollen recieved
]
end
Luke's answer is good and should fix your problem. I suspect, however, that you are going to be doing lots of these types of sums. You may wish to set up a to-report that you can use for whichever item you want to sum over, just by passing the item number and the name of the list of lists. It would look like this:
to-report sum-item [#pos #listoflists ]
let items map [ x -> item #pos x ] #listoflists
report reduce [ [a b] -> a + b] items
end
The first line extracts the relevant item (remember index from 0) into a new list which the second line sums.
You would then use it with set Tot_pol sum-item 0 Donnors
Here's an answer that is not actually responding to your question. Instead, it is a more NetLogo-ish way of doing what I think you are trying to do with your code.
to check-pol [m]
ask zsps with [morph = m]
[ let senders zsps with [distance myself <= 20 and morph != m]
set totpol sum [NMaleFlowers * 100 * round (distance myself)] of senders
]
end
Your code gets into levels of ask that I think are unnecessary. What I think you are doing with your list is keeping track of the pollen donors. But an agentset is a cleaner approach and then you can simply pull out the information you want from the agentset using of.
Further, when you ask zsps with[distance myself <= 20 and morph != m] to set variable values in your code, then THOSE agents (not the receiving agent) are the ones having their variables changed. I think you are trying to take the perspective of the receiver of pollen, who looks around and received pollen from the other agents that are close enough. So the receiving agent should have the value changed.
This is not tested.
I'm not 100% sure what you're after here (you may want to look at the Minimum, Complete, and Verifiable Example guidelines), but if I'm reading you right you want the sum of the first item for each entry in the Donners list.
As to why your approach didn't work- NetLogo is telling you with that error that you've used of with a list, but of only works with agents or agentsets. Instead, you have to use a list processing approach. The simplest way might be to use sum in conjunction with map first in order to get what you need:
to sum-first-item
let example-list [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ]
let sum-of-firsts sum map first example-list
print sum-of-firsts
end
To translate to Donnors, try:
set Tot_pol sum map first Donnors
That should work, but without reproducible a code example I can't check.
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
I want to create a list of count values of some variable (tot-turtles) increasing with each tick. I tried the below code but all time list is having single element of length 1. neither i is getting incremented. please correct me.
set tot-turtles count turtles
to go
let mylist [ ]
set mylist lput tot-turtles mylist ; show mylist
set i 1
foreach mylist [ ; print ? ;show i
set x ? - i ; print x
set i (i + 1) ;show i
]
end
I want to subtract elements of list in the following fashion where the length of list depends on the number of simulation run or till simulation ends, then
i need subtraction of element as element at (i + 1)th - element at ith position till the end of the list.
In the above code i is 1 then increments by 1 ie 2 and then continue to 1 2 1 2 1 2. mylsit always shows single element. Confused with "?" , it gives element of current position if i am not wrong, but how we know the current position?
Please help me out of these doubts and code. thanks a lot.
Thank you sir, yes i was doing mistake with local and global variable i checkd it later. and the thing i wanted is as below.
to setup
set mylist [ 0]
set item-difference 0
end
to go
set tot-turtles count tutles set
mylist lput tot-turtles mylist
let _n (length mylist)
set item-difference (( item ( _n - 1 ) mylist - item ( _n - 2 ) mylist )
end
I hope you got Allan sir.
It's a bit difficult to tell what you are after, but it seems you are using a local variable when you want a global variable. See if this offers some help:
globals [mylist]
to setup
ca
set mylist []
crt 10
end
to go
crt 1
set mylist lput (count turtles) mylist ; show mylist
end
to test
let _n (length mylist)
(foreach mylist n-values _n [? + 1] [
print ?1 - ?2
])
end
I wish to divide each element in a list by a number, I have tried the following:
Approach 1:
set item 0 (new-vec item 0 vec / number)
set item 1 (new-vec item 1 vec / number)
gives error this isn't something you can use set on
Approach 2:
foreach new-vec
[ set ? ? / number]
doesn't seem to work.
Please help. Thanks in advance.
This is because NetLogo lists are immutable data structures.
If you really want mutability you can always use the array extension, but once you've learned to use NetLogo's immutable lists properly, this is almost never necessary: the lists primitives are usually all that you need.
To divide all the numbers in a list by some other number, use map:
let new-vec [10 50 100]
let number 10
let divided-vec map [ ? / number ] new-vec
will assign the list [1 5 10] to divided-vec.
The map operation builds a new list by applying an operation to each element of the list you pass to it. In the example above, I assigned the new list to a new variable (divided-vec), but if you wanted, you could also assign it back to new-vec:
set new-vec map [ ? / number ] new-vec
This will behave as if you modified new-vec in place, though it won't be the case.
If you want to apply an operation to just one item in a list, you can do it with a combination of replace-item and item:
let my-list [2 4 6 8 10]
show replace-item 1 my-list (item 1 my-list * 100)
will show: [2 400 6 8 10]
This is how to do it in NetLogo 6, which changed anonymous procedures and thus how this is done in map:
let new-vec [10 50 100]
let number 10
let divided-vec map [ i -> i / number ] new-vec