Фильтрация списка списков на основе переменного числа комбинаций в Netlogo - PullRequest
2 голосов
/ 02 апреля 2019

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

Таким образом, в приведенном ниже примере я хотел бы иметь только первую комбинацию «a», «b», оставить первые две «a», «c», и сохраните последнее, (хотя в нем нет дальнейших комбинаций "a" и "d"):

Я пытался использовать несколько комбинаций фильтров и думал о способах сохранения элементов списка, без успеха для этой конкретной проблемы.

to setup
let temp-example []
set temp-example [["a" "b" 1 5] ["a" "b" 1 3] ["a" "c" 2 4] ["a" "c" 2 2] 
["a" "c" 2 1] ["a" "d" 4 1]]
end

Желаемым выводом является следующий список:

[["a" "b" 1 5]["a" "c" 2 4]["a" "c" 2 2] ["a" "d" 4 1]]

Ответы [ 2 ]

1 голос
/ 03 апреля 2019

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

to-report multifilter [ list_ ]
  ; Get the content pairs
  let content-pairs remove-duplicates map [ i -> sublist i 0 2 ] list_

  ; Reorganize list into sublists for each content pair
  let by-content-pairs map [ i -> filter [ j -> sublist j 0 2 = i ] list_ ] content-pairs

  ; Sort the sublists
  let sorted-by-value map [ i -> sort-with 3 i ] by-content-pairs

  ; Keep only first n items of each sublist,
  report reduce sentence map [ i -> keep-n 2 i ] sorted-by-value
end

to-report sort-with [ ind lst ]
  ; Sort the sublists by one of their indexed values
  report sort-by [ [ a b ] -> ( item ind a ) > ( item ind b ) ] lst
end

to-report keep-n [ ind lst ]
  ; Keep only as many values as are passed by ind, or the length
  ; of the list, whichever value is smaller
  let n item ind first lst
  if n > length lst [
    set n length lst
  ]
  report sublist lst 0 n
end

Позвоните multifilter в списке в формате, который вы показали, и вы должны получить желаемый результат:

to filter-multi
  let temp-example [
    ["a" "b" 1 5] ["a" "b" 1 3] ["a" "c" 2 1]
    ["a" "c" 2 4] ["a" "c" 2 2] ["a" "d" 4 1]
  ]

  print multifilter temp-example
end

Выход:

[[a b 1 5] [a c 2 4] [a c 2 2] [a d 4 1]]

Другой пример:

to filter-multi
  let temp-example [
    ["a" "b" 1 31] ["a" "b" 1 15] ["a" "b" 1 -53] ["a" "b" 1 10] ["a" "b" 1 3000]
    ["a" "c" 2 1] ["a" "c" 2 4] ["a" "c" 2 2] ["a" "c" 2 -10] ["a" "c" 2 14] ["a" "c" 2 40]
    ["a" "d" 4 1] ["a" "d" 4 12]
  ]

  print multifilter temp-example
end

Выход:

[[a b 1 3000] [a c 2 40] [a c 2 14] [a d 4 12] [a d 4 1]]
0 голосов
/ 03 апреля 2019

Я думаю, что это более или менее отвечает этому:

to-report frequency [an-item a-list]
    report length (filter [ i -> i = an-item] a-list)
end

; Reporter to keep the n most valuable combinations
to-report take [n xs]
  report sublist xs 0 min list n (length xs)
end

to go
  set temp-1[]
  set temp-2[]
  set temp-3[]
  set temp-4[]
  foreach temp-example[[i] ->
    set temp-1 lput (list item 0 i item 1 i) temp-1
  set temp-2 lput item 2 i temp-2]
    foreach temp-1[[j] ->
      set temp-3 lput frequency j temp-1 temp-3
    ]
  ;First: obtain all existing combinations between the two letters:
  foreach (range 0 (length temp-example)) [[j]->
    ifelse item j temp-2 <= item j temp-3 [set temp-4 lput take (item j temp-2) 
filter [i -> (list item 0 i item 1 i) = item j temp-1] temp-example temp-4];
     [set temp-4 lput item j temp-example temp-4]; caso contrario, colocar so ate aos 
item 2 j:
  ]
  show remove-duplicates temp-4
end
...