2014-01-17 54 views
1

我有一個基本的「餐巾紙算法」,它採用元組列表(2項)並更改它們。這是英文:python優化函數沒有循環

  1. 如果項目2是一個列表,改變第1項是串x
  2. 以其他方式改變第1項是y字符串

這裏是一個快速功能我把一起這樣做:

def f(objects): 
    list_type = "string_x" 
    other = "string_y" 
    hold = [] 
    for x in objects: 
     if isinstance(x[1],list): 
      hold.append((list_type,x[1])) 
     else: 
      hold.append((other,x[1])) 
    return hold 

我不認爲這是最有效的方式。這個算法非常簡單,只是一個基本的陳述。 這樣做會更有效嗎?

+0

燦你舉了一個你作爲'objects'傳遞的例子嗎? – brandonscript

+3

「高效」是指「快速」還是「可讀」或其他不同?是什麼讓你覺得它效率不高? – abarnert

+2

無論你如何去做,地圖,列表理解或其他,它必須是*某種排序*循環 – yuvi

回答

2

你可以讓這一點通過使用if表達短:

def f(objects): 
    list_type = "string_x" 
    other = "string_y" 
    hold = [] 
    for x in objects: 
     hold.append((list_type if isinstance(x[1], list) else other, x[1])) 
    return hold 

然後很容易變成理解,它更短,可能更易讀,更快一些:*

def f(objects): 
    list_type = "string_x" 
    other = "string_y" 
    return [(list_type if isinstance(x[1], list) else other, x[1]) 
      for x in objects] 

真的,我不知道那些局部變量是使事情更清楚:**

def f(objects): 
    return [("string_x" if isinstance(x[1], list) else "string_y", x[1]) 
      for x in objects] 

同時,如果你要與返回的列表做的唯一事情就是迭代(例如,因爲這只是轉換鏈中的一個),你根本不應該返回一個列表。無論是yield每個值,返回genexpr而不是listcomp,或者(如果你有Python的3.3+)獲得兩全其美:

def f(objects): 
    yield from (("string_x" if isinstance(x[1], list) else "string_y", x[1]) 
       for x in objects) 

*您還在做同樣的循環,所以你有完全相同的算法複雜性。然而,循環和列表追加都是通過採用一些快捷方式的自定義字節碼來實現的,這使得每次迭代更加高效。 (「自定義字節碼」的細節當然具體到CPython的和其他的字節碼兼容的實現比如PyPy,但在一般情況下,任何實現至少可能承擔list解析快捷方式。)

**這最後很可能稍微快一點,因爲它將常量加載到堆棧而不是本地變量。再次,它可能也有稍差的緩存局部性。如果真的很重要,請測試並看看。

+0

哇我不能相信我忘了你可以做,如果和其他在列表理解 –

+1

@RyanSaxe:「在列表理解」部分在這裏並不真正相關;這是一個通用的表達式,你可以做任何表達式。 (對於最後的過濾子句,還有'if'的理解特定用法,但我沒有在這裏使用它。) – abarnert

+0

感謝您的澄清。當我被允許時,我會在10分鐘內將此答案標記爲正確 –

0

使用列表理解會更有效和Python的(如果我沒看錯):

[("string_x" if isinstance(x[1], list) else "string_y", x[1]) for x in objects] 
+0

你不能'映射'一個表達式,只能是一個函數。也許你想要一個列表理解?或''地圖'與'lambda'? – abarnert

+0

固定。我對「地圖」的癡迷。 –

0

如果你需要檢查和更改列表中的所有項目,你需要一個循環,否則你不能這樣做。

使用列表理解可以使其更快一點,這可以減少每個列表項的所有附加功能。

def f(objects): 
    return [('string_x',x[1]) if isinstance(x[1],list) else ('string_y',x[1]) for x in objects] 

但是,如果你使用的是大名單的性能差異才可以看到

0

我挺喜歡做這種方式,但我可能是一個愚蠢的人:

strings = 'string_x', 'string_y' 

[(strings[isinstance(x[1],list)], x[1]) for x in objects]