我有两个美国州缩写列表(例如):
s1=['CO','MA','IN','OH','MA','CA','OH','OH']
s2=['MA','FL','CA','GA','MA','OH']
我最终想要的是(基本上是一个有序的频率表):
S=[['CA',2],['CO',1],['FL',1],['GA',1],['IN',1],['MA',4],['OH',4]]
我提出的方式是:
s3=s1+s2
S=[[x,s3.count(x)] for x in set(s3)]
这很有效 - 但是,我不知道这是非常有效的内存。
但是......有一个问题。
s1+s2
...太大而无法保留在内存中,所以我正在做的是追加到s1直到达到10K的长度(是的,资源有限),然后总结它(使用上面的列表理解步骤) ),删除s1的内容,并用下一个数据块重新填充s1(为了演示,仅在上面表示为's2')。 ......等等,直到它到达数据的末尾。
因此,对于循环的每次迭代,我想将列表'S'的'基础'列表与当前迭代的列表列表'相加。我的问题基本上是如何添加这些: (当前主数据):
S=[['CA',1],['CO',1],['IN',1],['MA',2],['OH',3]]
(新数据):
s=[['CA',1],['FL',1],['GA',1],['MA',2],['OH',1]]
...获取(新的主数据):
S=[['CA',2],['CO',1],['FL',1],['GA',1],['IN',1],['MA',4],['OH',4]]
......以某种合理有效的方式。如果这对字典或其他东西更好,我很好。不幸的是,我不能使用 ANY 远程专用的Python模块 - 我必须使用的是在关闭时可以想象的最简单的Python 2.6版本,锁定 - 资源匮乏的Linux环境(工作的危险)。非常感谢任何帮助!!
答案 0 :(得分:1)
您可以使用itertools.chain
有效链接两个迭代器:
import itertools
import collections
counts = collections.Counter()
for val in itertools.chain(s1, s2): # memory efficient
counts[val] += 1
collections.Counter
对象是专门用于计算的dict
...如果您知道如何使用dict
,则可以使用collections.Counter
。但是,它允许您更简洁地将上述内容写为:
counts = collections.Counter(itertools.chain(s1, s2))
另请注意,以下结构:
S=[[x,s3.count(x)] for x in set(s3)]
由于您在循环中调用s3.count
,因此也会非常低效。虽然,如果len(set(s3)) << len(s3)
注意,您可以手动进行链接&#34;做类似的事情:
it1 = iter(s1)
it2 = iter(s2)
for val in it1:
...
for val in it2:
...
答案 1 :(得分:1)
您可以根据需要多次运行Counter.update
,根据需要剪切数据以适应内存/流式传输。
import collections
counter = collections.Counter()
counter.update(['foo', 'bar'])
assert counter['foo'] == counter['bar'] == 1
counter.update(['foo', 'bar', 'foo'])
assert counter['foo'] == 3
assert counter['bar'] == 2
assert sorted(counter.items(), key=lambda rec: -rec[1]) == [('foo', 3), ('bar', 2)]
最后一行使用否定计数作为排序键,使更高的计数成为第一位。
如果您的 count 结构不适合内存,则需要一个(基于磁盘的)数据库,例如Postgres,或者可能只是一台具有更多内存和更高效密钥的计算机 - 价值商店,例如Redis。