Python:更新频率表(以列表的形式)

时间:2018-01-09 17:35:52

标签: python

我有两个美国州缩写列表(例如):

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环境(工作的危险)。非常感谢任何帮助!!

2 个答案:

答案 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。