Группировка списков по элементам в Netlogo

#list #foreach #netlogo

#Список #foreach #netlogo

Вопрос:

Допустим, у меня есть модель в Netlogo, и теперь я заинтересован в разработке репортера / процедуры, которая группирует списки в соответствии с их первым элементом. Для примера, скажем

 globals[list1 list2 list3 listoflists
ordered-list-a
  ordered-list-b
]

to setup
  set list1 ["a" "b" "c"]
  set list2 ["a" "c" "d"]
  set list3 ["b" "a" "c"]
  set listoflists (list list1 list2 list3)
end
  

Я хочу создать список списков таким образом, чтобы в каждом списке у вас были списки, начинающиеся с одного и того же элемента. Следовательно, желаемый результат

 [[["a" "b" "c"]["a" "c" "d"]]["b" "a" "c"]]]
  

то есть, где первый элемент объединяет все списки с буквой a на первом месте, а второй — все те, которые начинаются с буквы «b».

В идеале это должно быть масштабируемо для большого числа. Я пытался

 to create-list
  set ordered-list-a []
  set ordered-list-b []
   (foreach listoflists [[i] ->
    if item 0 i = "a" [set ordered-list-a lput i ordered-list-a]
  if item 0 i = "b" [set ordered-list-b lput i ordered-list-b]
  ])  
end
  

а затем создание списка из a и b, что делает свое дело, но а) это невероятно запутанно, б) требует, чтобы я заранее знал длину списка, чего у меня нет в реальном случае (это черепашья процедура) и в) кажется, что это много ненужного кодирования.

Есть ли какой-либо способ распространить описанную выше процедуру на любое количество начальных элементов (возможно, внутри цикла while?) и не требует создания списка для каждого начального элемента списка?

Большое спасибо

Ответ №1:

Я предполагаю, что желаемый результат должен быть: [[["a" "b" "c"]["a" "c" "d"]][["b" "a" "c"]]] . Я полагаю, что вы пропустили [ перед второй группой.

В любом случае, простым, но несколько неэффективным способом было бы:

 ; items is a list of items to be grouped
; key is an anonymous reporter that extracts the group label from a single item
to-report group-by [ items key ]
  let keys remove-duplicates map key items
  report map [ k -> filter [ x -> (runresult key x) = k ] items ] keys
end
  

Обратите внимание, что приведенная выше функция является полностью обобщенной функцией группировки. Чтобы использовать это в вашем случае, вы должны сделать:

 group-by listoflists [ l -> first l ]
  

Более эффективным способом было бы использовать table:group-items reporter из расширения table.

 table:group-items listoflists [ l -> first l ]
  

Комментарии:

1. Отлично! Большое спасибо, Брайан. Будет использовать расширение таблицы для минимизации кода (нужно сделать это для нескольких типов агентов …) работает просто великолепно! 🙂

2. И да, действительно, мне не хватало квадратной скобки, хорошо заметной.