Python TypeError:str对象不是迭代器
我有一个由单词组成的文件,每行一个单词。该文件如下所示:Python TypeError:str对象不是迭代器,python,dictionary,iterator,generator,Python,Dictionary,Iterator,Generator,我有一个由单词组成的文件,每行一个单词。该文件如下所示: aaa bob fff err ddd fff err 我想数一数这两个词一个接一个出现的频率 比如说, aaa,bob: 1 bob,fff:1 fff,err:2 等等。 我试过这个 f=open(file,'r') content=f.readlines() f.close() dic={} it=iter(content) for line in content: print line, next(line);
aaa
bob
fff
err
ddd
fff
err
我想数一数这两个词一个接一个出现的频率
比如说,
aaa,bob: 1
bob,fff:1
fff,err:2
等等。
我试过这个
f=open(file,'r')
content=f.readlines()
f.close()
dic={}
it=iter(content)
for line in content:
print line, next(line);
dic.update({[line,next(line)]: 1})
我得到了一个错误:
TypeError: str object is not an iterator
然后我尝试使用迭代器:
it=iter(content)
for x in it:
print x, next(x);
又犯了同样的错误。
请帮忙 您的值
x
包含一个字符串“ddd/ccc/etc”。它没有下一个next()
属于迭代器,用于从迭代器获取下一个元素。正确的调用方法是it.next()
但是,在完成使用迭代器中的所有元素后,将出现异常。所以,您需要捕获StopIteration异常
for x in it:
try:
line, next_line = x, it.next()
# do your count logic overhere
except StopIteration:
break
dic.update({[line,next_line]:1})
不起作用。您将跳过可能的组合。行
,与所有的STR
一样,是一个iter功能,这意味着它有一个iter
方法。但是next
与iterators一起工作,后者有一个\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法(在Python 2中,它是一个next
方法)。当解释器执行next(line)
时,它会尝试调用line.\uuuuuu next\uuuuuu
。由于行
没有\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法,因此它会引发类型错误:str对象不是迭代器
由于line
是一个iter功能,并且有一个\uuuuuuuuuuuuuuuuuuuu
方法,我们可以设置it=iter(line)
it
是一个iterator和\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但您正在查找文件中的下一行,请尝试以下操作:
from collections import defaultdict
dic = defaultdict(int)
with open('file.txt') as f:
content = f.readlines()
for i in range(len(content) - 1):
key = content[i].rstrip() + ',' + content[i+1].rstrip()
dic[key] += 1
for k,v in dic.items():
print(k,':',v)
输出(file.txt如OP中所示)
正如其他人提到的,不能在字符串行上使用next
。您可以使用itertools.tee
从文件对象创建两个独立的迭代器,然后使用collections.Counter
和zip
从行对创建计数器对象
from itertools import tee
from collections import Counter
with open('test.txt') as f:
# f = (line.rstrip() for line in f) # if you don't want the trailing new lines
f, ne = tee(f)
next(ne)
print(Counter(zip(f, ne)))
请注意,由于文件对象包含尾随有新行的行,如果您不希望,可以删除这些行
from collections import Counter
with open(file, 'r') as f:
content = f.readlines()
result = Counter((a, b) for a, b in zip(content[0:-1], content[1:]))
这将是一个字典,其键是行对(按顺序),其值是该对出现的次数。正如其他人所说,line是一个字符串,因此不能与next()方法一起使用。此外,不能将列表用作字典的键,因为它们是可散列的。可以改用元组。
一个简单的解决方案:
f=open(file,'r')
content=f.readlines()
f.close()
dic={}
for i in range(len(content)-1):
print(content[i], content[i+1])
try:
dic[(content[i], content[i+1])] += 1
except KeyError:
dic[(content[i], content[i+1])] = 1
还请注意,通过使用readlines()还可以保留每行的“\n”。您可能需要先将其剥离:
content = []
with open(file,'r') as f:
for line in f:
content.append(line.strip('\n'))
您可以使用2行和:
您还可以使用具有捕获前瞻性的:
with open(fn) as f:
lc=Counter((m.group(1)+','+m.group(2),) for m in re.finditer(r"(\w+)\n(?=(\w+))", f.read()))
您只需要跟踪上一行,文件对象返回它自己的迭代器,因此您根本不需要iter或readlines,在创建变量prev的一开始调用next一次,然后在循环中不断更新prev:
from collections import defaultdict
d = defaultdict(int)
with open("in.txt") as f:
prev = next(f).strip()
for line in map(str.strip,f): # python2 use itertools.imap
d[prev, line] += 1
prev = line
这将给你:
defaultdict(<type 'int'>, {('aaa', 'bob'): 1, ('fff', 'err'): 2, ('err', 'ddd'): 1, ('bob', 'fff'): 1, ('ddd', 'fff'): 1})
defaultdict(,{('aaa','bob'):1,('fff','err'):2,('err','ddd'):1,('bob','fff'):1,('ddd','fff'):1})
你认为下一步(事情)
会做什么?它并不意味着“在事物之后的事物”。旁白:一个解决方案是:pprint.pprint(collections.Counter(zip(content[0:],content[1:])。最常见的())
@user2357112:这就是我下一步的想法!下一步做什么?python文档说:“通过调用迭代器的next()方法从迭代器中检索下一项。如果给定默认值,则在迭代器耗尽时返回,否则将引发StopIteration。@rowana:您看到该参数如何被称为“迭代器”了吗?它将迭代器作为参数,而不是从迭代器中检索到的元素之一,并检索迭代器的下一项。(这将提升迭代器的状态,因此该迭代器的下一次next
调用或for
迭代将转到之后的项。)我想下一个问题是,你认为迭代器是什么<代码>行
不是迭代器。@user2357112,现在找到了!非常感谢。是不是下一个(它)
?@levi,谢谢你。它工作得很好。遗憾的是,我没有足够的积分来投票。当我这样做的时候,我会的!我想你是说它。uuu next_uuu():)@CraigBurgler不是,next()。测试它。有趣的是,它是Python 2中的it.next()
和Python 3中的it.\uuu next\uuu()
这是如何使用迭代器的一个很好的示例。想象一下next
有点像[].pop()
:它返回下一个值,但也从迭代器中删除它。它的一个重要用途是这样的伪reduce:获取初始值,然后循环其余值。
with open(fn) as f:
lc=Counter((m.group(1)+','+m.group(2),) for m in re.finditer(r"(\w+)\n(?=(\w+))", f.read()))
from collections import defaultdict
d = defaultdict(int)
with open("in.txt") as f:
prev = next(f).strip()
for line in map(str.strip,f): # python2 use itertools.imap
d[prev, line] += 1
prev = line
defaultdict(<type 'int'>, {('aaa', 'bob'): 1, ('fff', 'err'): 2, ('err', 'ddd'): 1, ('bob', 'fff'): 1, ('ddd', 'fff'): 1})