2017-07-03 73 views
2

我想從列表中隨機刪除一部分元素而不更改列表的順序。隨機從列表中刪除'x'元素

說我有一些數據,我想刪除其中1/4:

data = [1,2,3,4,5,6,7,8,9,10] 
n = len(data)/4 

我想我需要一個循環通過數據運行,並刪除隨機元素「N」次?所以像這樣:

for i in xrange(n): 
    random = np.randint(1,len(data)) 
    del data[random] 

我的問題是,這是這樣做的最'pythonic'的方式?我的列表將長約5000個元素,我想用不同的'n'值多次執行此操作。

謝謝!

回答

4

您可以使用random.sample這樣的:上述

import random 

a = [1,2,3,4,5,6,7,8,9,10] 

no_elements_to_delete = len(a) // 4 
no_elements_to_keep = len(a) - no_elements_to_delete 
b = set(random.sample(a, no_elements_to_keep)) # the `if i in b` on the next line would benefit from b being a set for large lists 
b = [i for i in a if i in b] # you need this to restore the order 
print(len(a)) # 10 
print(b)  # [1, 2, 3, 4, 5, 8, 9, 10] 
print(len(b)) # 8 

有兩點需要注意。

  1. 您並未修改原始列表,但可以。
  2. 你是不是真正刪除元素,而是保留元素,但它是同一個東西(你只需要調整比率)
  3. 缺點是列表理解的是恢復元素的順序

正如@koalo在評論中所說的,如果原始列表中的元素不是唯一的,則上述將無法​​正常工作。我可以很容易地解決這個問題,但是我的答案與@ JohnColeman發佈的答案完全相同。所以,如果這可能是這種情況,只需使用他的。

+0

謝謝!我實際上想保留'a'中留下的內容而不是刪除的內容 –

+0

@RichardHall查看更新 –

+0

如果元素在數組中出現多次,這不起作用! – koalo

4

順序刪除是一個壞主意,因爲列表中的刪除是O(n)。相反,做這樣的事情:

def delete_rand_items(items,n): 
    to_delete = set(random.sample(range(len(items)),n)) 
    return [x for i,x in enumerate(items) if not i in to_delete] 
+0

這也是偉大的,謝謝:) –

0

訂單是否有意義? 如果不是你可以這樣做:

shuffle(data) 
data=data[:len(data)-n] 
0

我建議使用numpy的索引作爲

import numpy as np 
data = np.array([1,2,3,4,5,6,7,8,9,10]) 
n = len(data)/4 
indices = sorted(np.random.choice(len(data),len(data)-n,replace=False)) 
result = data[indices]