很多时候我发现自己用Tally []计算出现次数,然后,一旦我放弃原始列表,必须添加(和加入)到该计数器列出来自另一个列表的结果.
这通常发生在我计算配置,事件,执行一些离散统计等时.
所以我为Tally聚合定义了一个非常简单但方便的函数:
aggTally[listUnTallied__List:{},listUnTallied1_List,listTallied_List] := Join[Tally@Join[listUnTallied,listUnTallied1],listTallied] //. {a___,{x_,p_},b___,q_},c___} -> {a,{x,p + q},b,c};
这样
l = {x,y,z}; lt = Tally@l; n = {x}; m = {x,t}; aggTally[n,{}] {{x,1}} aggTally[m,n,2},{y,1},{t,lt] {{x,3},{z,1}}
这个功能有两个问题:
1)表现
Timing[Fold[aggTally[Range@#2,#1] &,{},Range[100]];] {23.656,Null} (* functional equivalent to *) Timing[s = {}; j = 1; While[j < 100,s = aggTally[Range@j,s]; j++]] {23.047,Null}
2)它不验证最后一个参数是真正的Tallied列表还是null(尽管对我来说不那么重要)
有简单,优雅,快捷和有效的解决方案吗? (我知道这些要求太多了,但希望是免费的)
也许,这会满足您的需求吗?
aggTallyAlt[listUnTallied__List : {},listTallied : {{_,_Integer} ...}] := {#[[1,1]],Total@#[[All,2]]} & /@ GatherBy[Join[Tally@Join[listUnTallied,listTallied],First]
时间要好得多,并且对最后一个arg进行了基于模式的检查.
编辑:
这是一个更快的版本:
aggTallyAlt1[listUnTallied__List : {},_Integer} ...}] := Transpose[{#[[All,1,Total[#[[All,All,2]],{2}]}] &@ GatherBy[Join[Tally@Join[listUnTallied,First]
它的时间安排:
In[39]:= Timing[Fold[aggTallyAlt1[Range@#2,Range[100]];] Timing[s = {}; j = 1; While[j < 100,s = aggTallyAlt1[Range@j,s]; j++]] Out[39]= {0.015,Null} Out[40]= {0.016,Null}