恰逢县镇人大换届选举,看同事为印制选票等事忙忙碌碌,特制一题以纪念。 收到13位会员共21份答案,感谢老朋友的热情参与,祝贺新朋友获得成功,特别祝贺fjlhgs会员首次得到积分。 总也猜不透czzqb的圈子是什么圈子,遗憾。 题目不新鲜,提取不重复的值,在论坛老生常谈,现仅为其披一件马甲而已。 第1、2、3选区纯是题目的花絮,为检测公式提供不同数据,对公式的设计没有影响,我们不再提它。 题目要分两部分完成: 1、票数的不重复值; 2、相同票数的名字的不重复值。 其实这个解法不重要,关键在于效率优化。[em44]gdliyy版主为这个总结划定了主题!5个提速关键就是一个精辟的总结,让人受益匪浅:[em17] 提速关键: 1、 利用Frequency()代替Match(),速度稍快。 2、 利用--减负运算,代替1*,速度稍快。 3、 姓名公式中使用B4相对引用判断,减少数组公式运算量,速度倍增。 4、 使用SUM(--(_Count=$B4))/$B4代替人数统计,速度稍有提升。 5、 利用等差数列取姓名,省去MATCH查找比较判断,速度稍有提升。
提取票数的不重复值,首先根据姓名计算所得票数(即重复次数),用公式=COUNTIF(data02,data02),如下图所示: 先把它定义为名称:_Count=COUNTIF(data02,data02)
(所有名称定义引用gdliyy版主答案) 接着,提取_Count形如黄色区域的不重复值,两个公式都是经典解法: IF(MATCH(_Count,_Count,)=ROW(data02)-1,_Count) IF(FREQUENCY(_Count,_Count),_Count) 结果为: {6;;7;4;;;;;;;8;;;;;;;;;;;;;;;2;;;;;;;;;;;;;;;;;;;;;;;;;;1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;} 最后,用Small()函数按从小到大的顺序,把结果输出到B5:B11区域: SMALL(IF(FREQUENCY(_Count,_Count),_Count),ROW(A1)) 公式中,计算不重复票数的个数:COUNT(1/FREQUENCY(_Count,_Count)),公式用得也很好。 提取名字的不重复值,以C6:I6单元格公式为例(票数等于4的对应姓名): 1、用下面公式生成一内存数组,数值包含两部分信息,后三位表示姓名所在行号,前面部分表示姓名在所有姓名中的排位: IF(_Count=$B6,COUNTIF(data02,"<="&data02)*1000+ROW(data02)-1) 结果为: 以生成结果为关键字进行排序,结果如下:
根据上面数据的排列规律,用下面公式可提取出不重复值:
SMALL(IF(_Count=$B6,COUNTIF(data02,"<="&data02)*1000+ROW(data02)-1),(COLUMN(A3)-1)*$B6+1) 公式中的彩色部分,在单元格C6:I6中从左至右,结果依次为:1,5,9,13,17,21,25,即,取上面结果从小到大的位数,即跳过重复的姓名,取不重复的值。这便是gdliyy版主说的“利用等差数列取姓名”。 完整公式中的SUM(--(_Count=$B6))/$B6,票数等于4的记录数除以4,得到不重复的姓名个数,思路巧而妙。 提速的第6关键。公式中被反复调用的部分要尽量简化,以减少重复计算的次数,本题中的_Count在公式中被反复调用,如果把“以拼音为序”,即countif(data02,"<"&data02),加入到最底层的表达式中被反复调用,这样的公式就是低效率的公式。 这方面,gdliyy、chrisfang、lee123、封州大少、shuyee几位的公式中,都表现得很好。 其他朋友的答案中,也有很精彩的部分,这里不再一一提及。
[此贴子已经被作者于2006-9-21 14:22:50编辑过] |