1

我有这个代码

text = open("tags.txt", "r")
mylist = []
metalist = []

for line in text:
    mylist.append(line)

    if len(mylist) == 5:
        metalist.append(mylist)
        mylist.pop(0)

它打开一个文本文件,每行一个 POS 标签。然后它将前 5 个 POS 标签列表添加到 mylist,然后将其添加到 metalist。然后它向下移动到下一行并创建下一个 5 个 POS 标签序列。文本文件总共有大约 110k~ 个标签。我需要从金属师那里找到最常见的 POS 标签序列。我尝试使用计数器集合,但列表不可散列。解决这个问题的最佳方法是什么?

4

1 回答 1

1

正如其中一条评论所述,您可以简单地使用标签元组而不是它们的列表,这将与模块Counter中的类一起使用collections。以下是使用问题中代码的基于列表的方法的方法,以及一些优化,因为您必须处理大量 POS 标签:

from collections import Counter

GROUP_SIZE = 5
counter = Counter()
mylist = []

with open("tags.txt", "r") as tagfile:
    tags = (line.strip() for line in tagfile)
    try:
        while len(mylist) < GROUP_SIZE-1:
            mylist.append(tags.next())
    except StopIteration:
        pass

    for tag in tags:   # main loop
        mylist.pop(0)
        mylist.append(tag)
        counter.update((tuple(mylist),))

if len(counter) < 1:
    print 'too few tags in file'
else:
    for tags, count in counter.most_common(10):  # top 10
        print '{}, count = {:,d}'.format(list(tags), count)

但是,最好也使用deque模块collections中的 a 而不是 alist来执行您正在做的事情,因为前者非常有效,O(1),从任一端追加和弹出,而后者则为 O(n)。他们还使用更少的内存。

除此之外,从 Python v 2.6 开始,它们支持一个maxlen参数,该参数消除了pop()在达到所需大小后显式结束元素的需要——所以这里有一个基于它们的更高效的版本:

from collections import Counter, deque

GROUP_SIZE = 5
counter = Counter()
mydeque = deque(maxlen=GROUP_SIZE)

with open("tags.txt", "r") as tagfile:
    tags = (line.strip() for line in tagfile)
    try:
        while len(mydeque) < GROUP_SIZE-1:
            mydeque.append(tags.next())
    except StopIteration:
        pass

    for tag in tags:   # main loop
        mydeque.append(tag)
        counter.update((tuple(mydeque),))

if len(counter) < 1:
    print 'too few tags in file'
else:
    for tags, count in counter.most_common(10):  # top 10
        print '{}, count = {:,d}'.format(list(tags), count)
于 2013-06-21T21:34:21.877 回答