2017-05-18 71 views
0

列表中刪除的最小和最大數量從列表:在同一行的代碼

RawScores = [3.4,1.2,5.8,7.2,2.8,9.1,7.6,4] 

目前我使用下面的方法來刪除這兩個從列表中的最高和最低數量:

RawScores.remove(max(RawScores)) 
RawScores.remove(min(RawScores)) 

我想知道是否有替代或更有效的方法產生相同的結果,但只能在一行代碼上實現。

+1

你想刪除所有聯合最高值或只是一個? –

+1

此外,一個元素列表的期望行爲是什麼?這個案例在下面的答案中表現得非常不同。 – mwchase

+0

@Chris_Rands我應該說,對不起。是的,只有一個。 – LearningToPython

回答

4

這似乎微不足道,但你可以把兩個語句在同一行:

RawScores.remove(max(RawScores)); RawScores.remove(min(RawScores)) 

你必須修改到位名單的性能而不必先複製它。

在性能方面,這是迄今爲止提出的方法如何比較(上稍長列表,使差異更明顯):

def a(): 
    RawScores = [3.4,1.2,5.8,7.2,2.8,9.1,7.6,4] * 100 
    RawScores.remove(max(RawScores)), RawScores.remove(min(RawScores)) 

def b(): 
    RawScores = [3.4,1.2,5.8,7.2,2.8,9.1,7.6,4] * 100 
    RawScores = [x for x in RawScores if x != max(RawScores) and x != min(RawScores)] 

def c(): 
    RawScores = [3.4,1.2,5.8,7.2,2.8,9.1,7.6,4] * 100 
    RawScores = sorted(RawScores)[1:-1] 

%timeit a() # 10000 loops, best of 3: 66.3 µs per loop 
%timeit b() # 10 loops, best of 3: 49.3 ms per loop 
%timeit c() # 1000 loops, best of 3: 212 µs per loop 

原來的解決方案是迄今爲止最快的。

請不要太認真對待我的回答。把多條語句放在這樣一條線上是可怕的的做法。 Python代碼應該是美麗不能內聯:)


更新:我跑這另一臺計算機上,包括filter解決方案的兩個變種:

def d(): 
    RawScores = [3.4,1.2,5.8,7.2,2.8,9.1,7.6,4] * 100 
    RawScores = list(filter(lambda value: (value != max(RawScores) and value != min(RawScores)), RawScores)) 

def e(): 
    RawScores = [3.4,1.2,5.8,7.2,2.8,9.1,7.6,4] * 100 
    RawScores = list(filter(lambda value, ma=max(RawScores), mi=min(RawScores): (value != ma and value != mi), RawScores)) 


%timeit a() # 115 µs ± 3.13 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each) 
%timeit b() # 80 ms ± 1.49 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) 
%timeit c() # 377 µs ± 777 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each) 
%timeit d() # 78.7 ms ± 94.8 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) 
%timeit e() # 458 µs ± 22.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 

很明顯,這使得SENS計算的最小和最大隻有一次,而不是每一個元素。儘管如此,就地刪除是最快的。

+0

你厚顏無恥的流氓,有我的upvote。 – timgeb

+0

@timgeb當有人先說「1條線」時,我會滾動眼睛,因爲誰真的需要1條線而不是2條?第二,我認爲如果你要接受挑戰,分號就是作弊,否則幾乎所有的腳本都可以成爲1行! –

+0

那麼如何結合lambda比較使用過濾器? – Tjaart

1

肯定的:

without_min_max = [item for item in RawScores if item != max(RawScores) and item != min(RawScores)]

+1

這會創建一個新列表,不會修改退出的列表(並刪除所有關聯的最高值;可能會或可能不需要) –

+0

問題在哪裏指定這是必需的? – tompiler

+1

要修改原始列表,只需將左側更改爲'RawScores [:] =' – zondo

2

您可能要排序,切片您的列表,以便您刪除第一個和最後一個元素,除非你不能讓你的列表進行排序:

RawScores = sorted(RawScores)[1:-1] 
+0

排序會增加相當多的時間複雜度! –

+0

然而,這種解決方案給出了與原始代碼相同的結果(僅刪除多個最小/最大元素中的一個)。 – kazemakase

+0

@Chris_Rands是的,但我們沒有被要求加速結果,所以這是一種可能性,而不是明確的,這是肯定的 –

0

這裏是一個一個襯裏:

print(*sorted([3.4,1.2,5.8,7.2,2.8,9.1,7.6,4])[1:-1]) 

輸出:

2.8 3.4 4 5.8 7.2 7.6 
2

在一行中?是。高效?它

>>> RawScores = [3.4,1.2,5.8,7.2,2.8,9.1,7.6,4] 
>>> [x for x in RawScores if x != max(RawScores) and x != min(RawScores)] 
[3.4, 5.8, 7.2, 2.8, 7.6, 4] 

這工作好了,但max號是O(n)的複雜性被稱爲len(RawScores)倍(同樣爲min),這使得該解決方案的非效率。

你目前的解決方案是完全正常的,並運行在O(n)。

+0

這不是他們想要的,它創建一個新的列表並刪除所有聯合最高/最低值 –

2

你可以嘗試用一個過濾器:

nominmax = filter(lambda value: (value != max(RawScores) and value != 
min(RawScores)), RawScores)