Как отсортировать массив (большое N), заполненный списками, БЫСТРЫМ способом? - PullRequest
0 голосов
/ 08 апреля 2019

Мне нужен HYPER эффективный алгоритм сортировки.Встроенный Python .sort и сортировка выполняются быстро, но недостаточно быстро для моей задачи.Кроме того, я не могу использовать numpy.sort(), потому что мне нужно отсортировать массив (заполненный списками).Я не могу найти библиотеку GitHub, которая будет сортировать массив, заполненный списками.Мне также нужна возможность переключаться по возрастанию / по убыванию.Массив большой, и массив одинакового размера будет отсортирован тысячи раз для разных наборов данных.Любые ссылки или код будет высоко ценится!

ex1 = {'index': 0, 'value': 72}
ex2 = {'index': 1, 'value': 49}
ex9999 = {'index': 9999, 'value': 121}
array = [ex1, ex2, ex9999]
array.sort(key=lambda x: x['index'], reverse=False)
#how to sort array of lists in native python  (just too slow)

выше сортировки занимает 0,3 секунды (для точек данных 20K), НО с массивами 10K такого размера для сортировки, что время выполнения слишком медленное.Приемлемым будет 1/10 того, что я знаю, возможно из этого поста https://www.quora.com/What-is-the-absolute-fastest-way-to-sort-a-very-large-random-list-of-integers-in-python, просто не в состоянии сортировать массив, заполненный списками

1 Ответ

0 голосов
/ 08 апреля 2019

Вместо этого сортируйте кортежи.

tuples = [(d['index'], d['value'])
          for d in array]
tuples.sort()

Вы не опубликовали timeit данных. Покажите нам репрезентативные данные, и фактическое время, а затем опишите, какой пересмотренный график будет приемлемым. Не ясно, что вы можете победить Тимсорт , хотя, безусловно, лямбда-издержки будут значительными.

Если вам нужно еще быстрее, уберите неактуальный атрибут value:

indices = [d['index']
           for d in array]
indices.sort()

Несколько прошедших времен имеют значение:

  1. время для создания списка
  2. время сортировать список
  3. время использовать отсортированный список

Как указано, ваш вопрос недостаточно уточнен, поскольку он не ограничивает (1.) или (3.), и мы все знаем, что есть ложь, проклятая ложь и микро-ориентиры.

начальный (полусортированный) заказ, распределение ценностей, и шаблон доступа к отсортированному списку все имеет значение за прошедшее время.

Некоторые проблемы требуют только подмножества полной семантики Python3, и поддаются оптимизации numba . Вы не сказали нам достаточно сказать, применимо ли это к вашей бизнес-проблеме.

EDIT

Timsort на современной платформе может легко сортировать 4 миллиона элементов в секунду в форме кортежа, несколько меньше, чем если lambda накладные расходы необходимы.

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

В размещенном коде предложены индексы в последовательном (отсортированном) порядке, что казалось странным, но я воспроизвел этот аспект для сортировки кортежей в коде ниже.

Вот что я запускаю на ноутбуке Intel Core i7 Mac с частотой 2,9 ГГц:

#! /usr/bin/env python

from time import time
import random


def elapsed(fn):
    def print_elapsed(*args, **kw):
        t0 = time()
        ret = fn(*args, **kw)
        print(fn.__name__, '%.3f sec' % (time() - t0))
        return ret
    return print_elapsed


@elapsed
def get_values(k=2_000_000, base_val=42):
    return [dict(index=random.randint(0, 3e6), value=i + base_val + i % 10)
            for i in range(k)]


@elapsed
def get_tuples(dicts):
    return [(d['index'], d['value'])
            for d in dicts]


@elapsed
def get_indices(dicts):
    return [d['index']
            for d in dicts]


@elapsed
def sort_dicts(dicts):
    dicts.sort(key=lambda x: x['index'])


@elapsed
def sort_values(x, reverse=False):
    x.sort(reverse=reverse)


if __name__ == '__main__':
    dicts = get_values()
    sort_dicts(dicts)
    tuples = get_tuples(dicts)
    sort_values(tuples)
    indices = get_indices(dicts)
    sort_values(indices)

Выход для 2 M предметов:

get_values  3.307 sec
sort_dicts  2.121 sec
get_tuples  1.355 sec
sort_values 0.414 sec
get_indices 0.715 sec
sort_values 0.329 sec

Уменьшение размера задачи до заявленных вами 20 К пунктов,

get_values  0.034 sec
sort_dicts  0.006 sec
get_tuples  0.005 sec
sort_values 0.001 sec
get_indices 0.002 sec
sort_values 0.001 sec

или даже в десять раз больше 200 K элементов, которые сталкиваются с отсутствием кэша:

get_values  0.325 sec
sort_dicts  0.105 sec
get_tuples  0.111 sec
sort_values 0.027 sec
get_indices 0.064 sec
sort_values 0.021 sec

Трудно понять, как вы могли столкнуться с медлительностью, которую вы описали. Там должен быть какой-то невидимый аспект проблемы: вы работаете на медленном процессоре, или на каком-то уровне кеш целевого хоста маленький, или ДРАМ медленный, или есть другой аспект данных, которые вы сортируете, который вы еще не раскрыли нам. Часть вашего вопроса со списками не видна в опубликованном вами коде. Вы еще не обратились к таким методам, как Cython или Numba имеют отношение к вашей бизнес-проблеме. Может быть, у вас есть техническая проблема "медленной сортировки", но то, что вы поделились с нами, еще не является доказательством этого.

...