Сдвинуть последний элемент списка
Я ищу эффективный способ сместить последний элемент списка в Python в соответствующую позицию. например, если у нас есть список = [1, 3, 4, 5, 6, 2], мы должны получить список = [1, 2, 3, 4, 5, 6]. То, что я пробовал, не работает желаемым образом:
def sort1(lng, lst):
if len(lst) != lng:
return
else:
i = -2
last = lst[-1]
for x in lst:
if last < lst[i]:
lst[i] = last
i -= 1
print(lst)
sort1(6,[1,3,4,5,6,2])
It is giving me following result:
[1, 3, 4, 5, 2, 2]
[1, 3, 4, 2, 2, 2]
[1, 3, 2, 2, 2, 2]
[1, 2, 2, 2, 2, 2]
4 ответа
Вытащите элемент из списка и вставьте его обратно, используя bisect.insort_left
:
>>> import bisect
>>> lst = [1, 3, 4, 5, 6, 2]
>>> item = lst.pop()
>>> bisect.insort_left(lst, item)
>>> lst
[1, 2, 3, 4, 5, 6]
Подходящим методом является алгоритм сортировки вставкой, но теперь мы делаем это только для последнего элемента, поэтому вот оно:
list = [1, 3, 4, 5, 6, 2] # our list
item = list[len(list)-1] # last element
i = len(list)-2 # the starting element to compare the last element to
while item<list[i] and i>=0: # while place not found and index in range
list[i+1]=list[i] # move element at i to i+1
i-=1 # decrement i, so to compare with next left element
list[i+1]=item # when the loop is completed, we then have our last item's position in i+1
print(list) # this prints [1, 2, 3, 4, 5, 6]
Вы можете прочитать больше об алгоритмах сортировки вставками, что немного сложно объяснить здесь, я имею в виду, что это требует длинного объяснения и примеров, так что вы можете увидеть больше в Википедии: https://en.wikipedia.org/wiki/Insertion_sort
Не так сексуально, как ответ @Ashwini, но вы можете попробовать это.
Вместо:
lst[i] = last
(Который перезаписывает весь ваш массив последним значением, когда вы двигаетесь вниз)
Сделай это:
lst[i+1] = lst[i]
(это сместит все значения)
Тогда после всех циклов:
lst[i+1] = last
(Поместите последнее значение в правильное положение, где я +1 должен быть)
Если вам нужно написать свою собственную функцию, вы можете использовать enumerate и найти, где элемент находится между двумя значениями или он меньше или равен первому:
def sor1(lst):
# empty or list with single ele or last ele is larger than second last the list os sorted
if len(lst) < 2 or lst[-1] > lst[-2]:
return lst
last = lst.pop()
# if first value is larger than the last we need to insert last before the first
if lst[0] >= last:
lst.insert(0, last)
return lst
# else find first place where last falls between two values
for ind, ele in enumerate(lst):
if ele <= last <= lst[ind+1]:
lst.insert(ind+1,last)
return lst
Существует также библиотека Blist, где вставки 0(log n)
и он превосходит некоторые другие операции со списком Python, в некоторых случаях также верно обратное, поэтому это будет зависеть от того, что вы хотите сделать:
from blist import blist
lst = blist([1, 3, 4, 5, 6, 2])
Некоторые операции, в которых блист более эффективен, чем список:
Вставка или удаление из списка O (log n) O (n)
Вставка или удаление из списка O (log n) O (n)
Взятие кусков списков O (log n) O (n)
Создание мелких копий списков O(1) O(n)
Изменение фрагментов списков O(log n + log k) O(n+k)
Умножение списка для создания разреженного списка O (log k) O (kn)
Поддерживать отсортированные списки с помощью bisect.insort O(log**2 n) O(n)
Он немного превосходит список, используя insort_left, используя python 2.7:
In [32]: %%timeit
lst = list(range(1000000))+[90000]
item = lst.pop()
bisect.insort_left(lst, item)
....:
10 loops, best of 3: 38.5 ms per loop
In [33]: %%timeit
lst = blist(range(1000000))+blist([90000])
item = lst.pop()
bisect.insort_left(lst, item)
....:
10 loops, best of 3: 27.9 ms per loop