Dictionary Elixir:将列表减少到映射计数(模式匹配另一个参数上的映射键)

Dictionary Elixir:将列表减少到映射计数(模式匹配另一个参数上的映射键),dictionary,count,duplicates,pattern-matching,elixir,Dictionary,Count,Duplicates,Pattern Matching,Elixir,我有一个可能包含重复项的列表。我想计算列表中每个项目的实例数。我的计划是: list |> Enum.reduce(%{}, fn item, %{item => count}=acc -> %{acc | item => count + 1} item, acc -> Map.put(acc, item, 1) end) 但是,这无法编译,错误为在映射键匹配中非法使用变量项,映射只能使用^item对现有变量进行匹配 因此,我将第一个模式更改为item,%

我有一个可能包含重复项的列表。我想计算列表中每个项目的实例数。我的计划是:

list
|> Enum.reduce(%{}, fn
  item, %{item => count}=acc -> %{acc | item => count + 1}
  item, acc -> Map.put(acc, item, 1)
end)
但是,这无法编译,错误为
在映射键匹配中非法使用变量项,映射只能使用^item
对现有变量进行匹配

因此,我将第一个模式更改为
item,%%{^item=>count}=acc
。此时,错误变成
未绑定变量^item


我不知道该怎么办。我知道可以基于另一个参数对一个参数进行模式匹配(如比较函数的一个头的
fna,a->true),但在这种情况下显然不行。我试着用警卫做这件事,但是
Map.has_key?/2
不能放在警卫里。我在这里发现了很多关于在地图上进行匹配的问题,但是当要匹配的值来自另一个参数时,我没有发现这样做的问题。

好吧,在写问题时发现了这一点。我想我会分享,但如果其他人有更清洁的解决方案,欢迎他们使用:

我找到的最好的解决办法是。。。有点像是在内部咖喱其中一个参数,所以它是绑定的,纯粹是为了语法目的

list
|> Enum.reduce(%{}, fn item, acc ->
    f = fn %{item => count}=acc -> %{acc | item => count + 1}
            acc when is_map(acc) -> Map.put(acc, item, 1)
        end
    f.(acc)
  end)

修改映射中某个键的值并在该键不存在时插入,这正是
Map.update/4
所做的。要计算频率,默认值为
1
,更新fn只需将值加1(
&(&1+1)
):


您没有使用地图更新/4
的任何原因<代码>列表|>枚举减少(%{},fn x,acc->Map.update(acc,x,1,&(&1+1))结束)。。。。因为我显然没有像我想象的那样彻底地阅读这些文件。请回答这个问题,这样我就可以接受了。
iex(1)> [1, 2, :a, 2, :a, :b, :a] |>
...(1)> Enum.reduce(%{}, fn x, acc -> Map.update(acc, x, 1, &(&1 + 1)) end)
%{1 => 1, 2 => 2, :a => 3, :b => 1}