将列表 [[ "a" x ][ "a" y ]] 中的值聚合为 [ "a" (x + y) ]

Aggregating values in the list [[ "a" x ][ "a" y ]] to be [ "a" (x + y) ]


如果我有这样的列表:

let m [["a" 1]["a" 5]["b" 3]["b" 7]["c" 1]]

生成 [["a" 6]["b" 10]["c" 1]] 的正确语法是什么?

我试过了,但我总是得到 ERROR: Expected a variable name here

reduce [[[x y ][ x z ]] -> [ x y + z ]] m

谢谢。

Edit: @JenB made a revised, more clear version as response of this answer and has been accepted as the final answer.

这里的MVP(最有价值的程序)是item因为列表也包含列表。

为了获得预期的列表,这些是必要的要点:

  1. 按字母顺序对list列表进行排序()
  2. 根据字母求和。

要做第一点:

globals [the_list]

set the_list report sort-by [[a b] -> item 0 a < item 0 b] m

第二点:

to-report aggregate-lol [li]
  let result []
  let first_item item 0 li     ; first_item is also a list
  let li-length length li
  let li-end li-length - 1
  foreach (range 1 li-length)
  [ ? -> ifelse ? != li-end
    [ ifelse item 0 item ? li = item 0 first_item
      [ set first_item replace-item 1 first_item (item 1 first_item + item 1 item ? li) ]
      [ set result lput first_item result
        set first_item item ? li ]
    ]
    [ ifelse item 0 item ? li = item 0 first_item
      [ set first_item replace-item 1 first_item (item 1 first_item + item 1 item ? li)
        set result lput first_item result ]
      [ set result lput first_item result
        set result lput item li-end li result ]
    ]
  ]
  report result
end

所以结果会是

show aggregate-lol the_list 

我看到您将 foreach 尝试作为答案,而不是编辑您的问题。看起来你解决了它,干得好。但我想我应该提供一个使用相同逻辑但使用新列表语法的版本。您使用的是 v5,列表语法在 v6 中发生了重大变化。为了便于阅读,我还使用了 first 和其他类似的关键字。

这是一个独立的模型,您可以将它放在一个空的 NetLogo 会话和 运行 'testme' 过程中以查看它是如何工作的。

to testme
  let m [["a" 1]["a" 5]["b" 2]["c" 5]["b" 3]["b" 7]["c" 1]]
  print m
  print aggregate-lol m
end

to-report aggregate-lol [#li]
  ; sort the list alphabetically on first of pair
  let the-list sort-by [[a b] -> first a < first b] #li
  ; prime the loop
  let now-letter first first the-list
  let add-pair first the-list
  let result []
  ; loop from the second item to the end
  foreach butfirst the-list
  [ this-pair ->
    ifelse first this-pair = now-letter
    ; in same group so add
    [ set add-pair (list first add-pair (last add-pair + last this-pair)) ]
    ; in different group so output and use this item as start of next group
    [ set result lput add-pair result
      set add-pair this-pair
      set now-letter first this-pair
    ]
  ]
  ; append the final pair
  set result lput add-pair result
  
  report result
end

它也可以通过在命令中心输入类似 print aggregate-lol [["a" 1]["a" 5]["b" 2]["c" 5]["b" 3]["b" 7]["c" 1]] 的内容来工作。

这是一个使用高效列表基元的替代方案(密集代码且相当难读)。请注意,map 本质上是通过对给定列表中的每个项目应用函数并根据结果构建列表来完成原始构造中 foreach 的工作。 filter 选择所需的列表项(匹配第一个字母)。

to-report aggregate-dense [#li]
  ; list of unique first letters
  let all-firsts remove-duplicates map [ll -> first ll] #li
  ; by first letters, filter, sum and construct pair into list
  report map [ ff ->
    (list ff sum map [ll -> last ll] filter [ii -> first ii = ff] #li)
  ] all-firsts
end