2009-02-05 46 views
8

我在尋找的是最好的方式來說,'如果這個名單太短,延長到9個元素,並添加'選擇4','選擇5',等等,作爲附加要素。此外,用'選擇x'替換任何'無'元素。'替換「」和0也可以。延伸潛在的不完整名單的最pythonic方式

一個例子轉型是

['a','b',None,'c'] 

['a','b','Choice 3','c','Choice 5','Choice 6','Choice 7','Choice 8','Choice 9'] 

我最初的代碼被濫用的try/except和有一個差一錯誤,我沒有注意到;感謝joeforker和所有指出它的人。根據該意見,我嘗試了兩種短期的解決方案,測試同樣出色:

def extendChoices(cList): 
    for i in range(0,9): 
    try: 
     if cList[i] is None: 
     cList[i] = "Choice %d"%(i+1) 
    except IndexError: 
     cList.append("Choice %d"%(i+1) 

def extendChoices(cList): 
    # Fill in any blank entries 
    for i, v in enumerate(cList): 
    cList[i] = v or "Choice %s" % (i+1) 

    # Extend the list to 9 choices 
    for j in range(len(cList)+1, 10): 
    cList.append("Choice %s" % (j)) 

我覺得#2勝爲更Python,所以它是一個我會用。這很容易理解並使用常見的結構。拆分步驟是合乎邏輯的,並且會讓人更容易理解。

+0

當你回答這個問題,不要讓從選擇0編號的錯誤! – joeforker 2009-02-05 14:35:11

+0

如果一個選項是空字符串「」或0,你想將它顯示給用戶,還是你想要像對待None一樣對待它? – joeforker 2009-02-05 16:04:37

回答

10

zip不同,Python的map自動將較短的序列擴展爲None

map(lambda a, b: b if a is None else a, 
    choicesTxt, 
    ['Choice %i' % n for n in range(1, 10)]) 

你可以簡化lambda來

map(lambda a, b: a or b, 
    choicesTxt, 
    ['Choice %i' % n for n in range(1, 10)]) 

,如果它的好於choicesTxt一樣None治療等虛假狀物體。

3

我想我會做一些非常類似,但有一些整齊UPS:

for i in range(0,10): 
    try: 
    if choicesTxt[i] is None: 
     choicesTxt[i] = "Choice %d"%i 
    except IndexError: 
    choicesTxt.append("Choice %d"%i) 

其中唯一重要的兩個是隻趕上IndexError而不是任何異常,並以指數0.

而原始的唯一真正的問題是,如果choicesTxt是空的,當添加的選項將被關閉。

2

我認爲你應該把對數組的大小作爲一個單獨的步驟。爲此,如果陣列太短,請致電choicesTxt=choicesTxt+[None]*(10-len(choicesTxt))None選擇重新分配可以使用列表解析來完成。

0

我也建議使用xrange而不是範圍。 xrange函數根據需要生成數字。範圍提前生成它們。對於小型設備來說,這並沒有太大的區別,但是對於大型設備來說,節省可能會很大。

+1

在Python 3.0中,我們不必擔心這個問題,因爲範圍返回一個迭代器。 – joeforker 2009-02-05 14:42:07

1

什麼有關(似乎是一個字典 - 不是一個清單 - 當它不全

a = {1:'a', 2:None, 5:'e'} #test data 
[a[x] if x in a and a[x] is not None else 'Choice %d'%x for x in xrange(1,10)] 

編輯一次:如果這真是一個列表(不是字典):

b=['a',None,'b'] 
[b[x] if len(b)>x and b[x] is not None else 'Choice %d'%x for x in xrange(10)] 

需要Python 2.5我認爲(因爲三元運算符)?

(感謝joeforker固定的,它使用的鍵1到10,而不是0到10了;感謝SilentGhost:在比對象的has_key()或LEN()更Python)

+0

好的,所以xrange(1,10) – 2009-02-05 14:35:21

+0

.has_key()根本不是pythonic – SilentGhost 2009-02-05 14:39:32

+0

x在b中沒有任何意義;) – SilentGhost 2009-02-05 14:47:08

1

如果你不介意用「Choice%d」替換評估爲False的任何內容,然後result適用於Python 2.4。

如果你確實介意並且使用Python 2.5或更高版本,那麼使用result2_5_plus以及三元if的威力。

如果你不喜歡或者不能使用三元如果,然後採取的事實,即True == 1False == 0,使用x is None索引列表中的結果。

x = ["Blue", None, 0, "", "No, Yelloooow!"] 
y = [None]*9 

result = [(t or "Choice %d" % (i+1))\ 
     for i, t in enumerate(x + y[len(x):])] 

result2_5_plus = [(t if t is not None else "Choice %d" % (i+1))\ 
     for i, t in enumerate(x + y[len(x):])] 

result_no_ternary_if = [[t, "Choice %d" % (i+1)][t is None]\ 
    for i, t in enumerate(x + y[len(x):])] 

['Blue', 'Choice 2', 'Choice 3', 'Choice 4', 'No, Yelloooow!', 'Choice 6', 'Choice 7', 'Choice 8', 'Choice 9'] 
['Blue', 'Choice 2', 0, '', 'No, Yelloooow!', 'Choice 6', 'Choice 7', 'Choice 8', 'Choice 9'] 
+0

但隨後將'',0和[]替換爲「選擇n」。多數民衆贊成在不希望我想 – 2009-02-05 14:57:00

+0

他可能需要它,空字符串不是一個很好的選擇,以顯示給用戶。 – joeforker 2009-02-05 15:10:00

7

我最初的反應是「填空」列表中的擴展和分割成獨立的部分像這樣:

for i, v in enumerate(my_list): 
    my_list[i] = v or "Choice %s" % (i+1) 

for j in range(len(my_list)+1, 10): 
    my_list.append("Choice %s" % (j)) 

# maybe this is nicer for the extension? 
while len(my_list) < 10: 
    my_list.append("Choice %s" % (len(my_list)+1)) 

如果你堅持使用try...except的態度,也搭上了特定的異常如Douglas所示。否則,你會趕上的一切KeyboardInterrupts,RuntimeErrors,SyntaxErrors,...。你不想這樣做。

編輯:修復1索引列表錯誤 - 謝謝DNS

編輯:添加替代列表擴展

0
>>> in_list = ["a","b",None,"c"] 
>>> new = ['choice ' + str(i + 1) if j is None else j for i, j in enumerate(in_list)] 
>>> new.extend(('choice ' +str(i + 1) for i in range(len(new), 9))) 
>>> new 
['a', 'b', 'choice 3', 'c', 'choice 5', 'choice 6', 'choice 7', 'choice 8', 'choice 9'] 
3

你可以使用地圖(字典),而不是名單:

choices_map = {1:'Choice 1', 2:'Choice 2', 3:'Choice 12'} 
for key in xrange(1, 10): 
    choices_map.setdefault(key, 'Choice %d'%key) 

那麼你就地圖充滿了你的數據。
如果你想有一個列表,而不是你可以這樣做:

choices = choices_map.values() 
choices.sort() #if you want your list to be sorted 
#In Python 2.5 and newer you can do: 
choices = [choices_map[k] for k in sorted(choices_map)] 
1

我有點不清楚你爲什麼使用範圍(1,10);由於您使用的是optionsTxt [i],因此最終會跳過列表中第一個元素的None檢查。

此外,如果您要創建新列表,但明確要求添加到現有列表中,顯然有更簡單的方法來執行此操作。

我不認爲這樣更清潔或更快,但對您來說這是一個不同的想法。

for i, v in enumerate(choicesTxt): 
    choicesTxt[i] = v or "Choice " + str(i + 1) 

choicesTxt.extend([ "Choice " + str(i) for i in range(len(choicesTxt) + 1, 10) ]) 
1

我會做

for i, c in enumerate(choices): 
    if c is None: 
     choices[i] = 'Choice X' 

choices += ['Choice %d' % (i+1) for i in range(len(choices), 10)] 

這只是取代實際None值(沒有任何評估爲假),並擴展在分離步驟,我認爲是更清晰的列表。

1

我發現,當列表解析變長時,最好使用標準for循環。 幾乎別人一樣,但無論如何:

>>> in_list = ["a","b",None,"c"] 
>>> full_list = in_list + ([None] * (10 - len(in_list))) 
>>> for idx, value in enumerate(full_list): 
...  if value == None: 
...    full_list[idx] = 'Choice %d' % (idx + 1) 
... 
>>> full_list 
['a', 'b', 'Choice 3', 'c', 'Choice 5', 'Choice 6', 'Choice 7', 'Choice 8', 'Choice 9', 'Choice 10'] 
1
choices[:] = ([{False: x, True: "Choice %d" % (i + 1)}[x is None] for i, x in enumerate(choices)] + 
    ["Choice %d" % (i + 1) for i in xrange(len(choices), 9)]) 
1

你可以去用一個列表理解簡單:

extendedChoices = choices + ([None] * (10 - len(choices))) 
newChoices = ["Choice %d" % (i+1) if x is None else x 
    for i, x in enumerate(extendedChoices)] 

這追加None到您的選擇列表中,直到它至少有10個項目,枚舉結果,如果第X個元素缺失,則插入「選擇X」。

1
def choice_n(index): 
    return "Choice %d" % (index + 1) 

def add_choices(lst, length, default=choice_n): 
    """ 
    >>> add_choices(['a', 'b', None, 'c'], 9) 
    ['a', 'b', 'Choice 3', 'c', 'Choice 5', 'Choice 6', 'Choice 7', 'Choice 8', 'Choice 9'] 
    """ 

    for i, v in enumerate(lst): 
    if v is None: 
     lst[i] = default(i) 

    for i in range(len(lst), length): 
    lst.append(default(i)) 

    return lst 

if __name__ == "__main__": 
    import doctest 
    doctest.testmod() 
2

最簡單,最Python的對我來說是:

repl = lambda i: "Choice %d" % (i + 1) # DRY 
print ([(x or repl(i)) for i, x in enumerate(aList)] 
    + [repl(i) for i in xrange(len(aList), 9)]) 
1

井一行:

[a or 'Choice %d' % i for a,i in map(None,["a","b",None,"c"],range(10))]

雖然這將取代任何計算結果爲假(如無,「 ',0等)和「選擇n」。最好用"a or 'Choice %d' % i"替換一個函數,如果你不想要的話。

關鍵是可以使用參數爲None的map將列表擴展到所需位置中的None所需的長度。

一個整潔(更Python)版本將是:

 
def extend_choices(lst,length): 
    def replace_empty(value,index): 
     if value is None: 
      return 'Choice %d' % index 
     return value 
    return [replace_empty(value,index) for value,index in map(None,lst,range(length))] 

0

我的兩分錢......

def extendchoices(clist): 
    clist.extend([None]*(9-len(clist))) 
    for i in xrange(9): 
     if clist[i] is None: clist[i] = "Choice %d"%(i+1) 
0

是否確定更換任何虛假值,例如 '' 或0

>>> mylist = ['a','b',None,'c'] 
>>> map(lambda a,b:a or "Choice %s"%b, mylist, range(1,10)) 
['a', 'b', 'Choice 3', 'c', 'Choice 5', 'Choice 6', 'Choice 7', 'Choice 8', 'Choice 9'] 

如果您真的只能替換爲無

>>> map(lambda a,b:"Choice %s"%b if a is None else a, mylist, range(1,10)) 
['a', 'b', 'Choice 3', 'c', 'Choice 5', 'Choice 6', 'Choice 7', 'Choice 8', 'Choice 9'] 
0
>>> my_list=['a','b',None,'c'] 
>>> map (lambda x,y:x or 'Choice {}'.format(y+1),my_list,range(9)) 
['a', 'b', 'Choice 3', 'c', 'Choice 5', 'Choice 6', 'Choice 7', 'Choice 8', 'Choice 9']