Search code examples
listnetlogomeannested-lists

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


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.


Solution

  • 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