首页 > 解决方案 > 计数器无法正常工作

问题描述

以下代码查找文本文件以查看是否有任何匹配项。例如,一行可能是“charlie RY content”,下一行可能是“charlie content”。但是,计数器似乎已关闭并且计数不正确。

file = open("C:/file.txt", "rt")
data = file.readlines()
dictionary = dict()
counter = 0
count = 0
setlimit = 10 #int(input("Please enter limit for N. Then press enter:"))
parameter = ["RY", "TZ"]
for j in data:
    user = j.split()[0]
    identify = j.split()[1]
    for l in identify:
        #l = a[1:2]
        if user not in dictionary.keys() and identify not in parameter:
            count = 1
            data = dictionary.update({user:count})
            break
            #print(user, count,"<-- Qualifies")
        elif user in dictionary.keys() and identify not in parameter:
            data = dictionary.update({user: count})
            count += 1
            break
print(dictionary)

从代码中可以看出,它查找 RY 或 TZ 并忽略此行,如果满足没有此条件的行,则计数器将增加 1。

样本数据:

charlie TZ this is a sentence
zac this is a sentence
steve RY this is a sentence
bob this is a sentence
bob this is another sentence

预期输出:

{zac:1, bob:2}

标签: pythonpython-3.x

解决方案


如果你想增加计数,

count += 1

必须先到

dictionary.update({user: count})

换句话说,

elif user in dictionary.keys() and identify not in parameter:
    count += 1
    dictionary.update({user: count})
    break

请注意,dictionary.update(...)修改dictionary并返回None. 由于它总是返回None,因此无需将值保存在data.


或者,正如Martijn Pieters 所指出的,您可以使用

for j in data:
    ...
    if identify not in parameter:
        count += 1
        dictionary[user] = count

请注意,您不需要在两种不同的情况下处理分配。如果不在 中,分配dictionary[user] = count将创建新的键/值对,即使userdictionary,它也会分配新值count

请注意,只要条件为 True对于任何用户count,单个变量就会增加一。如果您想为每个用户独立增加一个,然后使用dictionary[user]

for j in data:
    ...
    if identify not in parameter:
        dictionary[user] = dictionary.get(user, 0) + 1

dictionary.get(user, 0)dictionary[user]如果user在 中则返回dictionary,否则返回 0。


另一种选择是使用collections.defaultdict

import collections
dictionary = collections.defaultdict(int)
for j in data:
    ...
    if identify not in parameter:
        dictionary[user] += 1

只要,不在 中dictionary = collections.defaultdict(int), 就会dictionary[user]被赋予默认值。自从int()userdictionary

In [56]: int()
Out[56]: 0

dictionary[user]user不在时自动分配默认值 0 dictionary


此外,虽然它们都返回相同的布尔值,但它user in dictionary比 Python 更惯用。user in dictionary.keys()事实上,当你说identify not in parameter.

虽然我们讨论的是成语,但通常最好使用-statementwith打开文件:

with open("data", "rt") as f:

因为这将保证f当 Python 离开with-statement 时文件句柄会自动为您关闭(通过到达语句内代码的末尾,或者即使引发异常。)


由于identify分配了字符串值,例如'TZ',循环

for l in identify:

T将, then等值赋给Z变量l. l没有在循环内使用,也没有明显的理由循环identify. 因此,您可能希望删除此循环。


测试集合中的成员资格平均是 O(1)(恒定速度)操作,而测试列表中的成员资格是 O(n)(时间通常随着列表的大小而增加。)所以最好做parameter一套:

parameter = set(["RY", "TZ"])

而不是调用j.split两次,

user = j.split()[0]
identify = j.split()[1]

你只需要调用一次:

user, identify = j.split(maxsplit=2)[:2]

请注意,这两个都假设j. 如果没有,原始代码片段将 raise IndexError: list index out of range,而第二个 raises ValueError: need more than 1 value to unpack

maxsplit=2告诉split在(最多)两个拆分完成后停止拆分字符串。如果j是具有许多分割点的大字符串,这可以节省一些时间。


所以把这一切放在一起,

import collections
dictionary = collections.defaultdict(int)
setlimit = 10 #int(input("Please enter limit for N. Then press enter:"))
parameter = set(["RY", "TZ"])
with open("C:/file.txt", "rt") as f:
    for line in f:
        user, identify = line.split(maxsplit=2)[:2]
        if identify not in parameter:
            dictionary[user] += 1

dictionary = dict(dictionary)
print(dictionary)

推荐阅读