Изменение отфильтрованных значений во вложенном списке

У меня есть вложенный список, в котором каждый подсписок структурирован следующим образом: [[xcor ycor] weight]. Каждый тик я хотел бы обновить вес в выборке этих подсписков.

Я создаю образец (например, размера 2) из ​​вложенного списка total, используя расширение Rnd (и очень полезные ответы/комментарии):

set total [ [[0 1] 1] [[2 3] 2] [[4 5] 3] [[6 7] 4] [[0 1] 1] ]
set sample rnd:weighted-n-of 2 total [ last ? ]

Затем я обновляю веса в выборке (скажем, умножая их на 2) и сопоставляю их с соответствующей парой [xcor ycor].

let newWeights (map [last ? * 2] sample)
let updatedSample (map list (map [first ?] sample) newWeights)

Как я могу заменить эти записи в total, имея в виду, что они могут содержать повторяющиеся записи?

Это кажется идеальной задачей для replace-item, но я не знаю, как создать соответствующий индекс, а затем передать соответствующее значение из updatedSample.


person Dave    schedule 01.04.2014    source источник
comment
Что должно произойти в случае дублирования ключей (ключи представляют собой [xcor ycor] пары)?   -  person Bryan Head    schedule 02.04.2014
comment
@BryanHead Веса всех повторяющихся ключей должны быть изменены в total, если этот ключ содержится в updatedSample. Извините, что не ясно выразился.   -  person Dave    schedule 02.04.2014


Ответы (1)


Это большая проблема. Используемая вами структура данных известна как список ассоциаций или сокращенно список, где ключи - [xcor ycor], а значения - веса. Учитывая вашу задачу, лучше использовать ключи для поиска, а не индексы. Таким образом, replace-item здесь не очень помогает. Вместо этого мы можем запустить map на total, используя значения из updatedSample, если они там есть, и по умолчанию использовать значения в total. Во-первых, нам нужна удобная функция для поиска в списках. В lisp (язык, повлиявший на NetLogo) это называется assoc. Вот:

to-report assoc [ key alist ]
  foreach alist [ if key = (first ?) [ report ? ] ]
  report false
end

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

to-report value-or-else [ value default ]
  report ifelse-value (value = false) [ default ] [ value ]
end

Наконец, мы можем написать функцию, которая выполняет отображение:

to-report update-alist [ alist updated-entries ]
  report map [ value-or-else (assoc first ? updated-entries) ? ] alist
end

Вот это в действии:

observer> show update-alist [[[0 1] 1] [[2 3] 2] [[4 5] 3] [[6 7] 4] [[0 1] 1]] [[[0 1] 10] [[4 5] 45]]
observer: [[[0 1] 10] [[2 3] 2] [[4 5] 45] [[6 7] 4] [[0 1] 10]]

Вы бы хотели назвать это как update-alist total updatedSample.

person Bryan Head    schedule 02.04.2014
comment
Это прекрасно и чрезвычайно поучительно. Большое спасибо! Наверное, я не совсем понимал, что я на самом деле делаю. - person Dave; 03.04.2014