Dictionary creation from sorted list
这个问题是关于嵌套字典理解的,我在问这个问题之前已经参考了Link1和Link2。我有一个列表,它的第一个元素是"无",其余的是一个已排序的正数列表。
1 | sorted_ar = [None, 10, 10, 12, 12, 12, 15, 25] |
我的要求是建立一本字典,如下:
1 | key_dict = {10: [3, 2], 12: [12, 3], 15: [6, 1], 25: [7, 1]} |
号
字典的值是两个元素列表,第一个元素是键出现次数的索引总和,第二个是出现次数。例如,对于元素12,索引之和=3+4+5=12,出现次数为3。下面的代码可以做到这一点。
1 2 3 4 5 | key_dict = {k:[0,0] for k in sorted_ar if k!=None} for i in range(len(sorted_ar)): if sorted_ar[i]: key_dict[sorted_ar[i]][0] += i key_dict[sorted_ar[i]][1] += 1 |
我的要求是使用字典理解来准备密钥字典。
我的尝试:
1 2 3 4 | key_dict = { sorted_ar[i]:[ key_dict[sorted_ar[i]][0] + i,key_dict[sorted_ar[i]][0] + 1] for i in range(1,len(sorted_ar)) if sorted_ar[i]!=None } |
。
但这给出了一些错误的结果
1 | key_dict = {10: [2, 1], 12: [5, 1], 15: [6, 1], 25: [7, 1]} |
在这种情况下,我应该如何写字典理解?
如果要使用排序,请查看
1 2 3 4 5 | from itertools import groupby filtered = ((i, v) for i, v in enumerate(sorted_ar) if v) grouped = ((v, list(g)) for v, g in groupby(filtered, lambda iv: iv[1])) result = {v: [sum(i for i, v in g), len(g)] for v, g in grouped} |
如果你愿意的话,你可以把这些都放在一个单独的表达中:
1 2 3 | result = {v: [sum(i for i, v in g), len(g)] for v, g in ( (v, list(g)) for v, g in groupby(( (i, v) for i, v in enumerate(sorted_ar) if v), lambda iv: iv[1]))} |
。
演示:
1 2 3 4 5 6 | >>> from itertools import groupby >>> sorted_ar = [None, 10, 10, 12, 12, 12, 15, 25] >>> filtered = ((i, v) for i, v in enumerate(sorted_ar) if v) >>> grouped = ((v, list(g)) for v, g in groupby(filtered, lambda iv: iv[1])) >>> {v: [sum(i for i, v in g), len(g)] for v, g in grouped} {10: [3, 2], 12: [12, 3], 15: [6, 1], 25: [7, 1]} |
或者作为一个长表达式:
1 2 | >>> {v: [sum(i for i, v in g), len(g)] for v, g in ((v, list(g)) for v, g in groupby(((i, v) for i, v in enumerate(sorted_ar) if v), lambda iv: iv[1]))} {10: [3, 2], 12: [12, 3], 15: [6, 1], 25: [7, 1]} |
。
另一方面,字典方法不需要对输入进行排序,因此可以在O(n)时间内运行(排序需要O(nlogn)时间)。
您可以尝试如下操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | sorted_ar = [None,10, 10, 12, 12, 12, 15, 25] track={} for i,j in enumerate(sorted_ar): if j not in track: track[j]=[(i,1)] else: track[j].append((i,1)) final_={} for i,j in track.items(): if i not in final_: final_[i]=(sum(list(map(lambda x:x[0],j))),sum(list(map(lambda x:x[1],j)))) print(final_) |
输出:
1 | {None: (0, 1), 10: (3, 2), 15: (6, 1), 12: (12, 3), 25: (7, 1)} |
。
好吧,我已经找到了一种方法来实现我的行为,不知道为什么,但诀窍是字典更新需要在理解之外进行。
1 2 3 4 5 6 7 8 9 10 11 12 13 | def my_summer(i,num,key_dict): key_dict[num][0] = key_dict[num][0]+i return key_dict[num][0] def my_counter(num,key_dict): key_dict[num][1] +=1 return key_dict[num][1] sorted_ar = [None, 10, 10, 12, 12, 12, 15, 25] key_dict = {k:[0,0] for k in sorted_ar if k!=None} key_dict = {sorted_ar[i]:[my_summer(i,sorted_ar[i],key_dict),my_counter(sorted_ar[i],key_dict)] for i in range(1,len(sorted_ar))} |
。
输出:
您可以尝试以下操作:
1 2 | sorted_ar = [None, 10, 10, 12, 12, 12, 15, 25] new_data = {i:[sum(c for c, b in enumerate(sorted_ar) if b == i), sorted_ar.count(i)] for i in sorted_ar if i} |
输出:
1 | {25: [7, 1], 10: [3, 2], 12: [12, 3], 15: [6, 1]} |
号