给出一个非常大的列表A,C,A,D,A,B,C,D,A,C
如何有效地获取当前元素和下一元素的计数?类似的东西:
AC, CA, 广告, DA, AB, 公元前, 光盘, DA, AC
A : {A:0, B:1, C:2, D:1}
B : {A:0, B:0, C:1, D:0}
C : {A:1, B:0, C:0, D:1}
D : {A:2, B:0, C:0, D:0}
或者如果我打印它,它会产生:
A B C D
A 1 2 1
B 1
C 1 1
D 2
答案 0 :(得分:4)
如果您的输入很大并且长度未知(可能是流式传输),那么使用迭代器是理想的选择。输出表不包含零计数的条目,因为我不假设您知道所有可能输入项的集合。
from itertools import tee, izip
# from http://stackoverflow.com/questions/5764782/iterate-through-pairs-of-items-in-a-python-list
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
inp = ['A', 'C', 'A', 'D', 'A', 'B', 'C', 'D', 'A', 'C']
table = {}
for a, b in pairwise(inp):
table.setdefault(a, {})
table[a].setdefault(b, 0)
table[a][b] += 1
print(table)
答案 1 :(得分:2)
您可以使用Counters字典:
from collections import Counter
import itertools
myList = ['A', 'C', 'A', 'D', 'A', 'B', 'C', 'D', 'A', 'C']
d = {x:Counter() for x in set(myList)}
for x,y in zip(myList,itertools.islice(myList,1,None)):
d[x].update(y)
print(d)
输出:
{'B': Counter({'C': 1}), 'A': Counter({'C': 2, 'B': 1, 'D': 1}), 'C': Counter({'A': 1, 'D': 1}), 'D': Counter({'A': 2})}
它在Python 3中相当有效,特别是在结合@ Rawing使用itertools.islice()
的出色想法之后。我测试了它:
myList = [random.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZ") for i in range(10**6)]
我的机器需要大约半秒钟,少于首先构建列表所花费的时间。
答案 2 :(得分:1)
您可以使用collections.Counter计算元素的出现次数,然后将其转换为2D字典:
import itertools
from collections import Counter
l = ['A', 'C', 'A', 'D', 'A', 'B', 'C', 'D', 'A', 'C']
# create a list of pairs of neighboring elements
neighbors = zip(l, itertools.islice(l, 1, None))
# count occurrences
counts = Counter(neighbors)
# convert counts to a 2D dictionary
output = {}
for k in counts:
if k[0] not in output:
output[k[0]] = {}
output[k[0]][k[1]] = counts[k]
print(output)
这将打印
{'C': {'D': 1, 'A': 1}, 'D': {'A': 2}, 'A': {'C': 2, 'D': 1, 'B': 1}, 'B': {'C': 1}}