сортировка больших текстовых данных - PullRequest
9 голосов
/ 16 августа 2011

У меня большой файл (100 миллионов строк значений, разделенных табуляцией, - около 1,5 ГБ). Какой самый быстрый известный способ сортировки по одному из полей?

Я попробовал улей. Я хотел бы посмотреть, можно ли это сделать быстрее с помощью Python.

Ответы [ 4 ]

17 голосов
/ 16 августа 2011

Рассматривали ли вы использование программы * nix sort?в натуральном выражении это, вероятно, будет быстрее, чем большинство сценариев Python.

Используйте -t $'\t', чтобы указать, что он разделен табуляцией, -k n, чтобы указать поле, где n - номер поля, и -o outputfile, если вы хотите вывести результат в новый файл.,Пример:

sort -t $'\t' -k 4 -o sorted.txt input.txt

Сортирует input.txt в своем 4-м поле и выводит результат в sorted.txt

6 голосов
/ 16 августа 2011

вы хотите построить индекс в памяти для файла:

  1. создать пустой список
  2. open файл
  3. читать его построчно (используя f.readline(), и сохранять в списке кортеж, состоящий из значения, по которому вы хотите отсортировать (извлекается с помощью line.split('\t').strip()), и смещения строки в файле (которое вы можно позвонить по номеру f.tell() до звонка f.readline())
  4. close файл
  5. sort список

Затем, чтобы распечатать отсортированный файл, снова откройте файл и для каждого элемента вашего списка, используйте f.seek(offset), чтобы переместить указатель файла в начало строки, f.readline(), чтобы прочитать строку и print строку ,

Оптимизация: вы можете сохранить длину строки в списке, чтобы вы могли использовать f.read(length) на этапе печати.

Пример кода (оптимизирован для удобства чтения, а не скорости):

def build_index(filename, sort_col):
    index = []
    f = open(filename)
    while True:
        offset = f.tell()
        line = f.readline()
        if not line:
            break
        length = len(line)
        col = line.split('\t')[sort_col].strip()
        index.append((col, offset, length))
    f.close()
    index.sort()
    return index

def print_sorted(filename, col_sort):
    index = build_index(filename, col_sort)
    f = open(filename)
    for col, offset, length in index:
        f.seek(offset)
        print f.read(length).rstrip('\n')

if __name__ == '__main__':
    filename = 'somefile.txt'
    sort_col = 2
    print_sorted(filename, sort_col)
3 голосов
/ 16 августа 2011

Разделить на файлы, которые можно отсортировать в памяти. Сортировка каждого файла в памяти. Затем объедините полученные файлы.

Слияние путем считывания части каждого файла для слияния. Одинаковое количество каждого файла оставляет достаточно места в памяти для объединенного результата. После слияния сохранил это. Повторное добавление блоков объединенных данных в файл.

Это минимизирует файловый ввод / вывод и перемещение файла на диске.

2 голосов
/ 16 августа 2011

Я бы сохранил файл в хорошей реляционной базе данных, проиндексировал бы его в интересующем вас поле и затем прочитал упорядоченные элементы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...