NetLogo: How to filter a list using a criterion wh

2020-07-24 03:04发布

问题:

My situation: I have two lists in NetLogo which are thought to correspond with each other, e.g. being two rows of of a matrix.

For example

set list-1 [1 2 2]
set list-2 [13 7 8]

where 1 is thought to be paired with 13, 2 with 7, and 2 with 8. These pairings may not be broken.

My problem:

I want to filter list-2 by applying a criterion on the corresponding elements of list-1. E.g. preserve an item of list-2 if the corresponding item equals 2

The result should be:

list-2: [7 8]

where the 13 is removed because the corresponding 1 does not equal 2.

How to program that in NetLogo?

My NetLogo version: 5.3.1

回答1:

I can think of many different ways to do this:

to go
  let list-1 [1 2 2]
  let list-2 [13 7 8]

  ; the most straightforward, imperative way:
  let list-3 []
  (foreach list-1 list-2 [
    if ?1 = 2 [ set list-3 lput ?2 list-3 ]
  ])
  print list-3

  ; an uglier imperative version using indices:
  let list-4 []
  let i 0
  while [ i < length list-1 ] [
    if item i list-1 = 2 [ set list-4 lput item i list-2 list-4 ]
    set i i + 1
  ]
  print list-4

  ; using reduce, sentence and map:
  print reduce sentence (map [
    ifelse-value (?1 = 2) [ ?2 ] [ [] ]
  ] list-1 list-2)

  ; using map, filter, and indices:
  print map [ item ? list-2 ] filter [
    item ? list-1 = 2
  ] n-values length list-1 [ ? ]    

  ; another variant using `filter`:
  print map last filter [ first ? = 2 ] (map list list-1 list-2)

end

That last one is by far my favorite, as I think it expresses the intent better than the others, but that might be subjective.

To make things reusable, you can isolate your preferred method in a reporter:

to-report filtered-by-first-list [ filtering-task list-1 list-2 ]
  report map last filter [
    (runresult filtering-task first ?)
  ] (map list list-1 list-2)
end

And then you can call it like this:

observer> show filtered-by-first-list task [ ? = 2 ] [1 2 2] [13 7 8]
observer: [7 8]

Converting all of this to NetLogo 6 syntax is left as an exercise to the reader. :-)