2014-04-01 2 views
2

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

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

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.

+0

Что должно произойти в случае дублирования ключей (ключи являются '[xcor ycor]' pair)? –

+0

@BryanHead Вес всех дубликатов ключей должен быть изменен в 'total', если этот ключ содержится в' updatedSample'. Извините за то, что я не понимаю. – Dave

ответ

2

Это отличная проблема. Используемая структура данных известна как association list, или для краткости alist, где ключи [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.

+0

Это прекрасно и очень поучительно. Большое спасибо! Наверное, я не совсем понял, что я на самом деле делаю. – Dave