[英]Most Pythonic way to sort a list from middle?
我有一個整數列表。 現在我想從中間排序。 我的意思是:
我設法編寫了以下代碼,但僅適用於奇數大小的列表。 為此編寫一個偶數版本並不難,但我覺得必須有更通用和“Pythonic”的方式來編碼。 實際上,我很驚訝以前從未有人問過這個微不足道的問題。
# Odd length, works
lst = [1, 3, 5, 7, 9, 10, 8, 6, 4, 2, 0] # Expected output [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
# Even length, doesn't work
#lst = [1, 3, 5, 7, 9, 8, 6, 4, 2, 0] # Expected output [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
mid = len(lst) // 2
dist = 1
res = [lst[mid]]
while dist <= mid:
res += sorted([lst[mid - dist], lst[mid + dist]], reverse=True)
dist += 1
assert len(res) == len(lst)
print(res)
注意,第一個數字后面的序列必須遵循距離+-1,+-2,+- [5, 4, 3, 2, 1]
5,4,3,2,1]的預期output是[3, 4, 2, 5, 1]
; [5, 3, 1, 0, 2, 4]
的預期 output 是[1, 0, 3, 2, 5, 4]
此外,如果有人可以為 function 提供reverse=True
或False
選項,那就太好了,這樣用戶就可以決定是先選擇更大還是更小的數字。
嘗試以下(雖然我更喜歡下面的遞歸版本):
lst_odd = [1, 3, 5, 7, 9, 10, 8, 6, 4, 2, 0]
lst_even = [1, 3, 5, 7, 9, 8, 6, 4, 2, 0]
def sorted_from_middle(lst, reverse=False):
left = lst[len(lst)//2-1::-1]
right = lst[len(lst)//2:]
output = [right.pop(0)] if len(lst) % 2 else []
for t in zip(left, right):
output += sorted(t, reverse=reverse)
return output
print(sorted_from_middle(lst_odd)) # [10, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1]
print(sorted_from_middle(lst_even)) # [8, 9, 6, 7, 4, 5, 2, 3, 0, 1]
print(sorted_from_middle(lst_odd, True)) # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
print(sorted_from_middle(lst_even, True)) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
print(sorted_from_middle([5, 4, 3, 2, 1], True)) # [3, 4, 2, 5, 1]
print(sorted_from_middle([5, 3, 1, 0, 2, 4], True)) # [1, 0, 3, 2, 5, 4]
這個想法right
將輸入列表分成left
兩部分; 通過首先將最中心的項目(如果有)附加到 output 列表(在代碼中這是通過從right
竊取項目來完成),使它們具有相同的長度。 讓left
反轉,以便在left
和right
中,第一個元素最靠近中心。 然后使用zip()
同時取兩個與中心距離為 1 的元素,比較它們,並根據 output 列表對它們進行 append。 然后移動到下一對項目,依此類推。
作為旁注,您也可以使用遞歸 function 來執行此操作,我認為它可以更干凈地處理偶數/奇數情況。
def sorted_from_middle(lst, reverse=False):
if len(lst) <= 1:
return lst
tail = sorted([lst[-1], lst[0]], reverse=reverse)
return sorted_from_middle(lst[1:-1], reverse) + tail
這個想法基本上只是 1)排除中間元素,如果它是奇數並保存它,然后 2)對由剩余列表前半部分的一個元素向后組織和剩余列表后半部分的另一個元素組成的每一對進行排序; 和 3) 展平將前中間元素添加為第一個元素的對列表(如果有)
import numpy
lst1 = [1, 3, 5, 7, 9, 10, 8, 6, 4, 2, 0]
lst1_out = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
lst2 = [1, 3, 5, 7, 9, 8, 6, 4, 2, 0]
lst2_out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
lst3 = [5, 4, 3, 2, 1]
lst3_out = [3, 4, 2, 5, 1]
lst4 = [5, 3, 1, 0, 2, 4]
lst4_out = [1, 0, 3, 2, 5, 4]
def sort_from_middle(lst,reverse=True):
lst = lst.copy()
N = len(lst)
if N == 1:
return lst
elif N == 2:
return sorted(lst, reverse=reverse)
else:
flatten_func = lambda t: [item for sublist in t for item in sublist]
n = int(numpy.floor(N/2.0))
x0 = [ lst.pop(n) ] if ((N%2) == 1) else []
N = len(lst)
return x0 + flatten_func([ sorted([x1,x2],reverse=reverse) for x1,x2 in zip(lst[int(N/2)-1::-1],lst[int(N/2):]) ])
print(lst1)
print(sort_from_middle(lst1))
print(lst1_out)
print(' \n')
print(lst2)
print(sort_from_middle(lst2))
print(lst2_out)
print(' \n')
print(lst3)
print(sort_from_middle(lst3))
print(lst3_out)
print(' \n')
print(lst4)
print(sort_from_middle(lst4))
print(lst4_out)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.