[英]Traversing a Python list and making in-place changes
我的任務是刪除一個特定元素的所有實例(在此示例中為“ 6”),並將其移動到列表的末尾。 要求是遍歷清單以進行內聯更改(不創建補充清單)。
輸入示例:[6,4,6,2,3,6,9,6,1,6,5]輸出示例:[4,2,3,9,1,5,6,6,6,6, 6]
到目前為止,我只能通過創建補充列表(違反任務要求)來做到這一點,因此不允許使用此工作代碼:
def shift_sixes(nums):
b = []
c = 0
d = []
for i in nums:
if i == 6:
b.insert(len(nums),i)
elif i != 6:
c = c +1
d.insert(c,i)
ans = d + b
return ans
我也嘗試過list.remove()
和list.insert()
但是在索引方面遇到了麻煩(當我執行insert()
時,索引會移動,然后將元素移到末尾):例如-
a = [6,4,6,2,3,6,9,6,1,6,5]
def shift_sixes(nums):
for i in nums:
if i == 6:
nums.remove(i)
nums.insert(nums[len(nums)-1], 0)
elif i != 0:
i
shift_sixes(a)
此外,我嘗試如下使用enumerate()函數,但是在b [idx]分配行的右側遇到了問題:
for idx, b in enumerate(a):
a[idx] = ???
在這里 , 這里和這里已經閱讀了其他stackoverflow條目,但是它們沒有解決元素向一端移動的問題。
將不勝感激此列表遍歷/就地切換問題。 非常感謝。
編輯@eph-謝謝。 這確實是一個優雅的回應。 我確定它將通過我的“沒有新名單”要求? 我肯定打算了解有關Lambda及其用法@falsetru的更多信息-謝謝您提醒添加/彈出組合(我嘗試通過list.remove()和list.insert()@tdelaney在我的原始查詢中執行此操作-同樣,也要謝謝您,您的答復與我的嘗試最接近,但似乎未通過[0,0,5]的測試。
遍歷時修改列表是個壞主意。 您可以復制以進行遍歷,也可以在遍歷期間生成新列表。
實際上,可以通過許多方式來完成該問題,例如:
>>> a.sort(key = lambda i: i == 6)
>>> a
[4, 2, 3, 9, 1, 5, 6, 6, 6, 6, 6]
為什么不嘗試這樣的事情?
基本上,方法是首先計算值的數量。 如果為0,則返回(因為如果為不在列表中的元素調用list.index方法,則Python會產生ValueError)。
然后,我們可以將值的第一個可接受的索引設置為列表的長度減去列表中存在的出現次數。
然后,我們可以組合list.pop / list.append以遍歷列表,直到所有所需的值都出現在列表的末尾。
def shift_value(lst, value):
counts = lst.count(value) # 5
if not counts:
return lst
value_index = len(lst) - counts
index = lst.index(value)
while index != value_index:
lst.append(lst.pop(index))
index = lst.index(value)
return lst
lst = [6,4,6,2,3,6,9,6,1,6,5]
print(shift_value(lst, 6))
編輯:這是效率極低的,上面建議的更好的答案。 這需要O(n ^ 2)時間,而不是O(n)時間。
此處的關鍵術語是“在線”。 您這樣做的方法是將每個i
num[i] = num[i+1]
到列表的末尾。
def shift_sixes(num):
for i, val in enumerate(num):
if val == 6:
# shift remaining items down
for j in range(i,len(num)-1):
num[j] = num[j+1]
# add 6 at the end
num[-1] = 6
return num
print(shift_sixes([1,9,4,6,2,7,8,6,2,2,6]))
print(shift_sixes([1,2,3]))
print(shift_sixes([6]))
print(shift_sixes([3]))
使用兩個跑步者。 首先從頭到尾檢查6s,第二次從頭到尾指向不是6的最后一項。繼續交換( a[i+1], a[i] = a[i], a[i+1]
)直到他們見面。
捕獲:這不是穩定的,就像穩定的排序。 但是我不認為這是必須的。
當在帶鍵盤的python解釋器前面時,將嘗試編寫工作代碼。
如果您需要穩定的排序(即非6的元素順序應保持不變),則解決方案是:
def move_to_end(data, value):
current = 0 # Instead of iterating with for, we iterate with index
processed = 0 # How many elements we already found and moved to end of list
length = len(data) # How many elements we must process
while current + processed < length: # While there's still data to process
if data[current] == value: # If current element matches condition
data.append(data.pop(current)) # We remove it from list and append to end
processed += 1 # Our index remains the same since list shifted, but we increase number of processed elements
else: # If current element is not a match
current += 1 # We increase our index and proceed to next element
if __name__ == '__main__':
print
print 'Some testing:'
print
for test_case in (
[1, 9, 4, 6, 2, 7, 8, 6, 2, 2, 6], # Generic case
[6, 6, 6, 6], # All items are 6
[1, 7], # No items are 6
[], # No items at all
):
print 'Raw:', test_case
move_to_end(test_case, 6)
print 'Becomes:', test_case
print
注意,該解決方案不僅保留了不匹配元素的順序,還保留了匹配元素的順序。 因此,例如,如果將檢查條件從“等於6”更改為“是偶數”,則所有與該條件匹配的元素都將移至列表的末尾,同時保持它們之間的順序。
為什么不保持簡單?
a = [6,4,6,2,3,6,9,6,1,6,5]
def shift_sixes(nums):
for i in range(0,len(nums)):
if nums[i] == 6:
nums.append(nums.pop(i))
>>> shift_sixes(a)
>>> a
[3, 9, 1, 5, 2, 4, 6, 6, 6, 6]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.