2010-12-22 40 views
2

我做的練習如下:差之間2個Python代碼

# B. front_x 
# Given a list of strings, return a list with the strings 
# in sorted order, except group all the strings that begin with 'x' first. 
# e.g. ['mix', 'xyz', 'apple', 'xanadu', 'aardvark'] yields 
# ['xanadu', 'xyz', 'aardvark', 'apple', 'mix'] 
# Hint: this can be done by making 2 lists and sorting each of them 
# before combining them. 

樣品溶液:

def front_x(words): 
    listX = [] 
    listO = [] 

    for w in words: 
    if w.startswith('x'): 
     listX.append(w) 
    else: 
     listO.append(w) 

    listX.sort() 
    listO.sort() 

    return listX + listO 

我的解決方案:

def front_x(words): 
    listX = [] 

    for w in words: 
    if w.startswith('x'): 
     listX.append(w) 
     words.remove(w) 

    listX.sort() 
    words.sort() 

    return listX + words 

,我測試了我的解決辦法,結果有點奇怪。以下是我的解決方案的源代碼:http://dl.dropbox.com/u/559353/list1.py。你可能想嘗試一下。

+2

你有什麼特別的問題,除了「我的代碼出了什麼問題」? – Bobby 2010-12-22 11:02:05

+0

-1:「結果有點不可思議」。含糊不清,難以回答。請提供您想要解決的具體問題。 – 2010-12-22 14:26:31

回答

3

的問題是,你遍歷列表,並從它刪除元素(修改它):

for w in words: 
    if w.startswith('x'): 
     listX.append(w) 
     words.remove(w) 

實施例:

>>> a = range(5) 
>>> for i in a: 
... a.remove(i) 
... 
>>> a 
[1, 3] 

此代碼的工作如下:

  • 獲取第一個元素,將其刪除。
  • 移到下一個元素。但它不再是1,因爲我們先前刪除0,因此1成爲新的第一個元素。因此下一個元素是2而跳過1
  • 34相同。
0

改變你正在迭代的列表會導致未定義的行爲。這就是示例解決方案創建兩個新列表而不是從源列表中刪除的原因。

for w in words: 
    if w.startswith('x'): 
    listX.append(w) 
    words.remove(w) # Problem here! 

請參閱this question關於此事的討論。它基本歸結爲列出遍歷列表索引的迭代器,而不必返回並檢查修改(這將會很昂貴!)。

如果你想避免創建第二個列表,你將不得不執行兩個迭代。一個用於遍歷words以創建listX,另一個用於迭代從words刪除的listX

1

兩個主要區別:

  1. 從內環路一個列表,其中被迭代的列表中刪除一個元素完全不是那麼回事Python編寫的。如果你使用Java,你會得到一個異常,說你正在修改一個正在迭代的集合。 Python顯然不會大喊這個錯誤。 @Felix_Kling在他的回答中解釋得很好。
  2. 另外您還在修改輸入參數words。因此,函數執行後,函數front_x的調用者將看到words被修改。除非有明確的預期,否則這種行爲最好避免。想象一下,您的程序正在使用words做其他事情。保留sample solution這兩個列表是更好的方法。
0

這暗示是誤導性的和不必要的,你可以做到這一點沒有排序和獨立結合兩個列表:

>>> items = ['mix', 'xyz', 'apple', 'xanadu', 'aardvark'] 
>>> sorted(items, key=lambda item: (item[0]!='x', item)) 
['xanadu', 'xyz', 'aardvark', 'apple', 'mix'] 

內置的排序()函數,告訴它什麼選項主要論點排序方式。在這種情況下,您希望爲原始列表中的每個元素創建一個元素,如(False,'xanadu')或(True,'apple'),您可以使用lambda創建元組。