将列表[[“ a” x] [“ a” y]]中的值汇总为[“ 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

谢谢。

解决方法

我看到您尝试了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
,

编辑:@JenB对这个答案here做出了一个修订的,更清晰的版本,并被接受为最终答案。

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

为了获得想要的列表,这些是必须要做的事情:

  1. 按字母顺序()对列表列表进行排序
  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