Home > Mobile >  How to use a command all the 4th item nested lists in netlogo
How to use a command all the 4th item nested lists in netlogo

Time:05-21

I have built a long nested list having the following profile: set my-list [A 1 2 3 4] [B 5 6 7 8] [C 9 10 11 12]

I'd like to apply the meancommand to the fourth item of each nested lists, so in the example to 4 8 12

but without building a list in loop that would look like [4 8 12] (to save computing time).

Is it possible ?

using let comp mean (item i item 4 (my-list)) or let comp mean (item 4 (my-list)) aren't obviously working.

The answer would be useful to other part of the model that I'm building.

Thanks for your time.

CodePudding user response:

First things first: did you mean to say that such nested list is built such as the one below?

set my-list [[A 1 2 3 4] [B 5 6 7 8] [C 9 10 11 12]]

Note the extra pair of square brackets, that make this actually a list of lists. Even if that was the case, NetLogo wouldn't let you use that syntax:

  • Either because A, B and C are lacking quotation marks if you intend them to be strings;
  • Or because, if A, B and C are variables, NetLogo expects literal values (we can get around this problem by using (list ...) instead of []).

In the first case, it would have to be:

set my-list [["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]

In the second case, it would have to be:

set my-list (list (list a 1 2 3 4) (list b 5 6 7 8) (list c 9 10 11 12))

All of the above just to make sure we are all on the same page (in general, please make sure that the code you post in your question is valid for the language you are asking about. As you can see, it would save a lot of time and space!).

Anyway I imagine that what you come up with is something of this type:

[["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]

I would use a while loop to iterate through the inner lists. You can create a local variable to keep track of the sum of the numbers you extract as you iterate through the inner lists, and then divide that sum by the number of times you extracted a number:

to check-mean
  let my-list [["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
  
  let the-sum 0
  
  let i 0
  while [i < length my-list] [
    set the-sum (the-sum   item 4 (item i my-list))
    set i i   1
  ]
  
  print the-sum / i
end

CodePudding user response:

The map primitive is very well suited for these sorts of calculations with lists. It allows you to perform a reporter separately for each part of a list and then returns the results as a new list.

let test-list [1 2 3]
show map [x -> x   1] test-list
;> [2 3 4]

In your case, you would use map to cycle through your list of lists, and use the item primitive to extract the necessary number from each sublist (map [x -> item 4 x ] my-list). This then returns them as a list of which you can take the mean.

to check-mean-2
  
  let my-list [["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
  
  let my-mean mean map [x -> item 4 x ] my-list

  print my-mean

end

EDIT: Although mine looks more efficient on first glance, Matteo's version actually runs quicker (at least on my machine)

globals [my-list]

to setup
  
  set my-list [["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
  
end

to check-mean
  
  let timer-list []
  
  repeat 10 [
    
    reset-timer
    
    repeat 1000000 [
      
      let the-sum 0
      
      let i 0
      while [i < length my-list] [
        set the-sum (the-sum   item 4 (item i my-list))
        set i i   1
      ]
      let my-mean the-sum / i
    ]
    
    
    
    let the-timer timer ; ~0.207
    show the-timer
    set timer-list lput the-timer timer-list 
    
  ]
  
  show word "mean: " (mean timer-list) ; 0.210
  
  
end

to check-mean-2
    
  let timer-list []
  
  repeat 10 [
    
    reset-timer
    
    repeat 1000000 [
      let my-mean mean map [x -> item 4 x ] my-list
    ]
    
    let the-timer timer
    show the-timer
    set timer-list lput the-timer timer-list 
    
  ]
  
  show word "mean: " (mean timer-list) ; 0.235
  
end

ANOTHER EDIT: Finally two more versions using reduce instead of map. Version 3 is the fastest of them all but you should take notice of the fact that my-list has a 0 added to it in this version. This might make is slightly less conveniet for other purposes. You can also add this 0 to it during the calculation as seen in version 4, but that drives up the time again.

to check-mean-3
    
  set my-list [0 ["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
  
  
  let timer-list []
  
  repeat 10 [
    
    reset-timer
    
    repeat 1000000 [
      
      let my-sum reduce [ [x y] -> x   item 4 y] my-list
      
      let my-mean my-sum / (length my-list - 1)
  
    ]
    
    let the-timer timer
    show the-timer
    set timer-list lput the-timer timer-list 
    
  ]
  
  show word "mean: " (mean timer-list) ; 0.170
  
end

to check-mean-4
    
  set my-list [["a" 1 2 3 4] ["b" 5 6 7 8] ["c" 9 10 11 12]]
  
  
  let timer-list []
  
  repeat 10 [
    
    reset-timer
    
    repeat 1000000 [
      
      let my-new-list fput 0 my-list
      
      let my-sum reduce [ [x y] -> x   item 4 y] my-new-list
      
      let my-mean my-sum / (length my-list - 1)
  
    ]
    
    let the-timer timer
    show the-timer
    set timer-list lput the-timer timer-list 
    
  ]
  
  show word "mean: " (mean timer-list) ; 0.226
  
end
  • Related