delaye
delaye

Reputation: 1399

Sort a patch set or agentset with two conditions in NetLogo

My patches have cost and gain attributes, and I would like to sort a list of patches with the minimum cost and the maximum gain. The sort-by function works for sorting on one attribute but how can I sort on both attributes?

Upvotes: 2

Views: 1159

Answers (1)

Nicolas Payette
Nicolas Payette

Reputation: 14972

To sort an agentset on many attributes, you can use either sort-by or sort-on:

patches-own [ cost gain ]

to sort-patches
  ca
  ask patches [
    set cost random 100
    set gain random 100
  ]

  let patches-sorted-by sort-by [
    ([ cost ] of ?1 > [ cost ] of ?2) or
    ([ cost ] of ?1 = [ cost ] of ?2 and [ gain ] of ?1 < [ gain ] of ?2)
  ] patches
  show map [[ list cost gain ] of ? ] patches-sorted-by

  let patches-sorted-on sort-on [ (cost * -1000) + gain ] patches
  show map [[ list cost gain ] of ? ] patches-sorted-on
end

Which one you prefer is up to you. Using sort-on requires to carefully construct your formula (i.e., the above would not work if you can have gains greater than 1000) but is slightly less verbose.

Edit: a more general way of sorting on multiple criteria

OK, this is probably overkill for your situation, but I came up with something a lot more general:

to-report sort-by-criteria [ criteria items ]
  ; `criteria` needs to be a task that returns a list of numbers
  report sort-by [
    compare-lists (runresult criteria ?1) (runresult criteria ?2)
  ] items
end

to-report compare-lists [ l1 l2 ]
  report ifelse-value (empty? l1 or empty? l2) [ false ] [
    ifelse-value (first l1 = first l2)
      [ compare-lists but-first l1 but-first l2 ]
      [ first l1 < first l2 ]
  ]
end

What you need to pass sort-by-criteria is a task that, given one of the items that you want to sort, will report a list of numbers according to which your items will be sorted.

In your case, you would use it like:

let sorted-patches sort-by-criteria (
  task [[ list (-1 * cost) gain ] of ? ]
) patches

For two criteria, it's probably not worth using, but if you had a long list of criteria, it would probably be a lot easier and clearer to use than any of the other methods.

Upvotes: 3

Related Questions