我编写了以下代码来帮助我抓取文件中的重复行并列出每个重复行的行号。
此代码在函数中时不。但是,当我将代码放在一个函数中时,如下所示,它的行为并不像我期望的那样。
我希望“getallDups”函数的值存储在可变数据中。
#!/usr/bin/env python
filename = '/tmp/test.txt'
f = open(filename, "r")
contentAslist = f.read().splitlines()
def getallDups():
lc = 0
mystring = ""
for eitem in contentAslist:
lc += 1
if contentAslist.count(eitem) > 1:
mystring = lc,eitem
return(mystring)
data = getallDups()
print data
以上代码仅存储第一个重复的行。它没有列出所有重复的行。
如何修改此代码以完全按照我的要求进行操作?如何修改以将已定义函数的值存储在变量“data”中,然后我可以使用它。
答案 0 :(得分:1)
你的麻烦在于你在一个循环中返回,这意味着你永远不会获得剩余的数据。您可以通过简单地将return
换成yield
并将检索调用更改为:
data = list(getallDups())
这将使您的循环完全完成。
答案 1 :(得分:1)
您在函数内的循环中放置了一个return
语句:返回导致函数在第一次迭代时结束...可能的方法是返回一个列表(并在循环中收集字符串)或更改功能到发电机。
返回列表:
filename = '/tmp/test.txt'
f = open(filename, "r")
contentAslist = f.read().splitlines()
def getallDups():
mylist = []
lc = 0
for eitem in contentAslist:
lc += 1
if contentAslist.count(eitem) > 1:
mylist.append((lc, eitem)) # append the duplicated line to a list
return mylist # return the fully populated list
data = getallDups()
print data
生成器版本:
filename = '/tmp/test.txt'
f = open(filename, "r")
contentAslist = f.read().splitlines()
def getallDups():
mylist = []
lc = 0
for eitem in contentAslist:
lc += 1
if contentAslist.count(eitem) > 1:
yield (lc, eitem) # yield duplicate lines one at a time
data = list(getallDups()) # build a list from the generator values
print data
答案 2 :(得分:1)
如果您希望它返回更多结果,则需要计算更多结果。您需要将结果添加到列表中,而不是返回它找到的第一个匹配项,并返回列表:
contentAslist = [
"abcd",
"efgh",
"abcd",
"ijk",
"lmno",
"ijk",
"lmno",
"ijk",
]
def getallDups():
lc = 0
result = []
for eitem in contentAslist:
lc += 1
if contentAslist.count(eitem) > 1:
result.append((lc, eitem))
return result
data = getallDups()
print data
然而,这是一个非常低效的方法,O(N ^ 2),因为list.count()方法对于列表中的N个项是O(N),我们称之为N次。
更好的方法是使用哈希。请注意,此处的返回类型非常不同,但可能更有用,并且可以轻松转换为原始格式。
import collections
contentAslist = [
"abcd",
"efgh",
"abcd",
"ijk",
"lmno",
"ijk",
"lmno",
"ijk",
]
def getallDups():
lc = 1
# OrderedDict is same as "{}" except that when we iterate them later they're in the order that we added them.
lhash = collections.OrderedDict()
for line in contentAslist:
# get list of line numbers matching this line, or empty list if it's the first
line_numbers = lhash.get(line, [])
# add this line number to the list
line_numbers.append(lc)
# Store the list of line numbers matching this line in the hash
lhash[line] = line_numbers
lc += 1
return lhash
data = getallDups()
for line, line_numbers in data.iteritems():
if len(line_numbers) > 1:
print line, ":",
for ln in line_numbers:
print ln,
print
上述解决方案是O(N)。
示例输入:
abcd
efgh
abcd
ijk
lmno
ijk
lmno
ijk
输出:
abcd : 1 3
ijk : 4 6 8
lmno : 5 7