我有一个大的排序文件,每行一个数字。我想输出一些大小的每个范围内的数字。例如,将范围设为10,将输入设为
1
4
34
37
42
48
53
输出应为[2, 1, 3, 2, 2, 2, 1]
。这是[1,4], [4], [34,37,42], [37,42], [42,48], [48,53], [53]
的长度。我认为这可以使用deque
来解决,但是,主要是作为编程练习并且还使用更少的内存,我试图通过打开文件两次来解决,并且有两个不同的指针进入文件。一个用于读取列表的下一个左端,另一个用于读取新的右手。所以我的代码有
fin1 = open(file, 'r')
fin2 = open(file, 'r')
我认为循环超过fin1,当范围变得太大时,我会更多地阅读fin2,直到范围足够小并继续踩下fin1和fin2。
但是我不能让这个工作。似乎不喜欢我为同一个文件打开两个文件句柄。怎么能这样做?
答案 0 :(得分:3)
这是一个使用itertools.tee()
模拟从句柄读取的解决方案,但实际上只打开一个:
from itertools import tee
def sliding_range(file, size):
fin1, fin2 = tee(int(ln.strip()) for ln in open(file) if ln.strip())
n = 1
next(fin2)
val2 = next(fin2)
for val1 in fin1:
while val2 is not None and val2 <= val1 + size:
n += 1
try:
val2 = next(fin2)
except StopIteration:
val2 = None
break
yield n
n -= 1
示例(将您的示例数据复制到'test.txt'):
>>> list(sliding_range('test.txt', 10))
[2, 1, 3, 2, 2, 2, 1]
答案 1 :(得分:1)
这是一个实现,可能有更好的方法,但这应该工作。我假设您在问题中发布了相同的输入。
def ranges(n):
f = open("tmp.txt")
while True:
i = f.tell()
try:
curr = int(f.readline().rstrip())
except ValueError:
break # EOF
j = f.tell()
while True:
k = f.tell() # End of range location
try:
next = int(f.readline().rstrip())
except ValueError:
break # EOF
if next < n or (next - curr) < n:
continue
else:
break
f.seek(i) # Go to beginning of range
r = []
while f.tell() < k:
r.append(int(f.readline().strip()))
print(r)
f.seek(j) # Go to line after beginning of range
>>> ranges(10)
[1, 4]
[4]
[34, 37, 42]
[42, 48]
[48, 53]
[53]
答案 2 :(得分:1)
编辑:我之前的实施是deque解决方案(并非完美解决方案)。这是带有2个文件指针的解决方案:
def sliding_ranges(filename=r"C:\Temp\data.txt", N=10):
f1, f2 = open(filename), open(filename)
k, res, i1, i2, r1, r2 = 1, [], 0, 0, 1, 1
while True:
while r2 and (not i2 or i2 - i1 < N):
r2, k = f2.readline(), k + 1
if r2: i2 = int(r2)
while r1 and (not i1 or not r2 or i2 - i1 > N):
r1, k = f1.readline(), k - 1
if i1: res.append(k)
if r1: i1 = int(r1)
if not r1: break
return res
>>> sliding_ranges(r"C:\Temp\data.txt", 10)
[2, 1, 3, 2, 2, 2, 1]
PREVIOUS:这是一次通过的实现。当你正在遍历时,你会继续计算列表的长度
f = open(r"d:\temp\data.txt")
d, res, N = [], {}, 10
for j in f:
i = int(j)
if i not in res: res[i] = 1
for k, v in res.items():
if i - k > N:
d.append(v)
del res[k]
elif k != i:
res[k] += 1
d = d + [v for v in res.values()]
这里是每次迭代中的对象列表
d []
res {}
d []
res {1: 1}
d []
res {1: 2, 4: 1}
d [2, 1]
res {34: 1}
d [2, 1]
res {34: 2, 37: 1}
d [2, 1]
res {34: 3, 42: 1, 37: 2}
d [2, 1, 3, 2]
res {42: 2, 48: 1}
d = [2, 1, 3, 2, 2, 2, 1]
答案 3 :(得分:0)
我不确定你为什么这样做,但回答你的问题(关于文件I / O而不是计算值)你需要一个文件句柄和两个文件指针。
使用文件句柄f
打开文件后,f.tell()
会告诉您文件中的位置,f.seek(pos)
会将指针移回给定位置。< / p>
f.seek(pos,how)
采用可选的第二个参数,为您提供搜索搜索方式的灵活性(将how
设置为0从文件的开头搜索,1从当前位置设置,2从结束)。这允许您使用pos
作为参考的偏移量,而不是严格地从头开始。