Я считаю, что файл с отображением памяти будет самым быстрым решением. Я попробовал четыре функции: функцию, отправленную OP (opcount
); простая итерация по строкам в файле (simplecount
); readline с картографированной памятью (mmap) (mapcount
); и решение для считывания буфера, предложенное Николаем Харечко (bufcount
).
Я выполнял каждую функцию пять раз и вычислял среднее время выполнения для текстового файла с 1,2 млн. строк.
Windows XP, Python 2.5, 2 ГБ оперативной памяти, процессор AMD 2 ГГц
Вот мои результаты:
mapcount : 0.465599966049
simplecount : 0.756399965286
bufcount : 0.546800041199
opcount : 0.718600034714
Изменить: номера для Python 2.6:
mapcount : 0.471799945831
simplecount : 0.634400033951
bufcount : 0.468800067902
opcount : 0.602999973297
Таким образом, стратегия чтения буфера, по-видимому, является самой быстрой для Windows / Python 2.6
Вот код:
from __future__ import with_statement
import time
import mmap
import random
from collections import defaultdict
def mapcount(filename):
f = open(filename, "r+")
buf = mmap.mmap(f.fileno(), 0)
lines = 0
readline = buf.readline
while readline():
lines += 1
return lines
def simplecount(filename):
lines = 0
for line in open(filename):
lines += 1
return lines
def bufcount(filename):
f = open(filename)
lines = 0
buf_size = 1024 * 1024
read_f = f.read # loop optimization
buf = read_f(buf_size)
while buf:
lines += buf.count('\n')
buf = read_f(buf_size)
return lines
def opcount(fname):
with open(fname) as f:
for i, l in enumerate(f):
pass
return i + 1
counts = defaultdict(list)
for i in range(5):
for func in [mapcount, simplecount, bufcount, opcount]:
start_time = time.time()
assert func("big_file.txt") == 1209138
counts[func].append(time.time() - start_time)
for key, vals in counts.items():
print key.__name__, ":", sum(vals) / float(len(vals))
Простой и общий способ -
julia> as_ints(a::AbstractArray{CartesianIndex{L}}) where L = reshape(reinterpret(Int, a), (L, size(a)...))
as_ints (generic function with 1 method)
julia> as_ints(indx)
2×9 reshape(reinterpret(Int64, ::Array{CartesianIndex{2},1}), 2, 9) with eltype Int64:
1 3 4 1 2 4 1 1 4
2 2 2 3 3 3 4 5 5
. Это работает для любой размерности, делая первое измерение индексом в CartesianIndex.
Одним из возможных способов является hcat(getindex.(indx, 1), getindex.(indx,2))
julia> @btime hcat(getindex.($indx, 1), getindex.($indx,2))
167.372 ns (6 allocations: 656 bytes)
10×2 Array{Int64,2}:
4 1
3 2
4 2
1 3
4 3
5 3
2 4
5 4
1 5
4 5
Однако, обратите внимание, что вам не нужно - и, следовательно, вероятно, не должно - привести ваши индексы в форму 2D-матрицы. Вы можете просто сделать
PyPlot.scatter(getindex.(indx, 1), getindex.(indx, 2))