Относительный порядок элементов в списке
Я пишу функцию, которая принимает список чисел и возвращает список из относительно позиционированных элементов.
то есть, если мой вход в указанную функцию [1, 5, 4] выход будет [0, 2, 1], так как 1 является самым низким элементом, 5 является самым высоким и 4 в середине, все элементы являются уникальными значениями или set ()
но код говорит, функция, которую я до сих пор
def relative_order(a):
rel=[]
for i in a:
loc = 0
for v in a:
if i > v:
loc += 1
rel.append(loc)
return rel
это работает, но поскольку я отправляю большие списки в эту функцию, и я должен сравнить каждый элемент со всеми элементами в каждой итерации, это занимает ~5sec со списком 10.000 элементов.
мой вопрос в том, как я могу улучшить скорость указанной функции и, возможно, быть немного более Питоническим, я пробовал списки понимания, но мои навыки Python отсутствуют, и я только придумал императивный способ реализации этой проблемы.
5 ответов
Это можно записать как понимание списка, как это:
lst = [1, 5, 4]
s = sorted(lst)
[s.index(x) for x in lst]
=> [0, 2, 1]
и вот еще один тест, используя пример @frb:
lst = [10, 2, 3, 9]
s = sorted(lst)
[s.index(x) for x in lst]
=> [3, 0, 1, 2]
вот еще один ход, который должен быть более эффективным, чем сохранение .index
' ing в список, как указано, что не будет повторяющихся значений, поэтому мы можем сделать поиск O (1) вместо линейного... (и фактически отвечает требованиям):
>>> a = [10, 2, 3, 9]
>>> indexed = {v: i for i, v in enumerate(sorted(a))}
>>> map(indexed.get, a)
[3, 0, 1, 2]
метод, который у вас есть, и текущий ответ занимает порядок N^2 времени.
Это должно работать в log (n) time:
def relative_order(a): positions = sorted(range(len(a)), key=lambda i: a[i]) return sorted(range(len(a)), key = lambda i: positions[i])
это все еще журнал заказов (n), и поэтому он должен работать и для ваших больших списков.
изменить:
за пределами лямбда.
def relative_order(a):
l = sorted(a)
# hash table of element -> index in ordered list
d = dict(zip(l, range(len(l))))
return [d[e] for e in a]
print relative_order([1, 5, 4])
print relative_order([2, 3, 1])
print relative_order([10, 2, 3, 9])
[0, 2, 1]
[1, 2, 0]
[3, 0, 1, 2]
алгоритм должен быть таким же эффективным, как сортировка, но использовать дополнительное пространство.
Ваш вопрос о сортировке. Я бы рекомендовал использовать Numpy или "числовой Python". Numpy-это модуль Python, оптимизированный для "быстрого, компактного, многомерного массива". Это пакет для научных вычислений на Python. http://www.numpy.org/
import numpy as np
input_array = np.array([1, 5, 4])
sorted_indices = np.argsort(input_array)
print sorted_indices
#[0 2, 1]
Я также добавил вывод профилировщика на основе массива size 50000
. Он показывает, что этот метод (около 4x) быстрее, чем использование Python