Как сохранить список списков, отсортированных по мере их создания

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

dataList = [

['blah', 2, 3, 4],

['blahs', 6, 7, 8],

['blaher', 10, 11, 12],

]

Я хочу, чтобы dataList отсортировался по второму элементу подкаталога: dataList [] [1]

Я думал, что могу использовать insort или bisect прямо, когда я хочу их добавить, но я не могу понять, как заставить его посмотреть на второй элемент подписок.

Любые мысли здесь? Я просто добавлял данные до конца, а затем делал линейную сортировку, чтобы найти вещи позже. Но, бросьте несколько десятков тысяч суб-списков здесь, а затем ищите 100 тыс. Элементов, и требуется некоторое время.

Ответ 1

dataList.sort(key=lambda x: x[1])

Это сортирует список по месту, вторым элементом в каждом элементе.

Как уже отмечалось в комментариях, гораздо эффективнее сортировать только один раз (в конце). Встроенный метод сортировки Python был сильно оптимизирован для быстрой работы. После тестирования это похоже на то, что встроенная сортировка последовательно примерно в 3,7 раза быстрее, чем с помощью метода кучи, предложенного в другом ответе, в разных списках размеров (я тестировал размеры до 600000).

Ответ 2

Зависит от нескольких вещей, но первое, что приходит в голову, это использовать модуль heapq:

import heapq
heap = []
for row in rows:
    heapq.heappush(heap, (row[1], row))

Это создало бы кучу, полную кортежей, где первый элемент - это элемент, который вы хотите отсортировать, а второй элемент - это строка.

Самый простой способ прочитать их из кучи - скопировать его, а затем поп-элементы:

new_heap = list(heap)
while new_heap:
    _, row = heapq.heappop(new_heap)
    print row

Время выполнения вставки каждого элемента в кучу O(lg N), поэтому для создания кучи потребуется время O(N lg N), а для всплывающих элементов из кучи также требуется время O(lg N), поэтому O(N lg N) потребуется время пересечь его.

Если эти компромиссы не идеальны, вы можете использовать двоичное дерево поиска (ни одна из них не существует в стандартной библиотеке, но их легко найти), или, как предложили другие комментаторы, отсортируйте строки после их чтения: rows.sort(key=lambda row: row[1]).

Теперь, на практике, если вы не имеете дело с очень большим количеством строк, почти наверняка будет быстрее отсортировать список на месте после его загрузки (т.е. с помощью метода .sort())... Поэтому попробуйте несколько вещей и посмотреть, что лучше всего работает.

Наконец, bisect является плохой идеей, потому что для вставки в списки Python требуется время O(N), поэтому для вставки элементов с bisect потребуется время O(N lg N) для каждого элемента, поэтому общее время O((N lg N) * N) = O(N**2) времени.