我有一個已撥號(nums_dialed)的電話號碼列表。 我也有一組電話號碼,這是在客戶的辦公室(client_nums) 數量如何有效地找出有多少次我叫特定的客戶端(總)Python中元素的數量設置
例如:
>>>nums_dialed=[1,2,2,3,3]
>>>client_nums=set([2,3])
>>>???
total=4
問題是我有一個large-ish數據集:len(client_nums)〜10^5;和len(num_dialed)〜10^3。
我有一個已撥號(nums_dialed)的電話號碼列表。 我也有一組電話號碼,這是在客戶的辦公室(client_nums) 數量如何有效地找出有多少次我叫特定的客戶端(總)Python中元素的數量設置
例如:
>>>nums_dialed=[1,2,2,3,3]
>>>client_nums=set([2,3])
>>>???
total=4
問題是我有一個large-ish數據集:len(client_nums)〜10^5;和len(num_dialed)〜10^3。
哪位客戶在他的辦公室有10^5
號碼?你是否爲整個電話公司工作?
總之:
print sum(1 for num in nums_dialed if num in client_nums)
這會給你儘可能快的數量。
如果你想這樣做了多個客戶端,使用相同的nums_dialed
列表中,那麼你可以先緩存上的每個數字的數據:
nums_dialed_dict = collections.defaultdict(int)
for num in nums_dialed:
nums_dialed_dict[num] += 1
然後就總結每個客戶端上的:
sum(nums_dialed_dict[num] for num in this_client_nums)
這將比爲每個客戶端重複遍歷整個數字列表快得多。
>>> client_nums = set([2, 3])
>>> nums_dialed = [1, 2, 2, 3, 3]
>>> count = 0
>>> for num in nums_dialed:
... if num in client_nums:
... count += 1
...
>>> count
4
>>>
即使對於您引用的大數字,應該也是相當有效的。
那是非常流行的方式來做到在單次排序列出的某種組合:
nums_dialed = [1, 2, 2, 3, 3]
client_nums = [2,3]
nums_dialed.sort()
client_nums.sort()
c = 0
i = iter(nums_dialed)
j = iter(client_nums)
try:
a = i.next()
b = j.next()
while True:
if a < b:
a = i.next()
continue
if a > b:
b = j.next()
continue
# a == b
c += 1
a = i.next() # next dialed
except StopIteration:
pass
print c
因爲「集」是無序集合(不知道爲什麼它使用哈希值,而不是二進制樹或排序列表),在那裏使用它是不公平的。如果你喜歡列表或者通過更復雜的東西來生成有序的迭代器,你可以通過「平分」實現自己的「集合」。
在Python 2.7使用collections.Counter:
dialed_count = collections.Counter(nums_dialed)
count = sum(dialed_count[t] for t in client_nums)
或者乾脆:LEN(過濾器(拉姆達X:X在client_nums,nums_dialed)) – ony 2010-03-27 07:44:58
@ony:這不是簡單的。而且速度較慢並且使用更多的內存,因爲它在計算'len'之前必須建立一個全新的列表。列表解析和生成器表達式比大多數情況下使用'filter'和'map'更好,特別是當您需要創建並調用一個新函數來使用它們時。 – nosklo 2010-03-27 07:55:11
@nosklo:對不起,我的錯。 python2中的「filter」和「map」使用列表,但如果python3中的「len」將強制列表構建,那將會非常奇怪。 – ony 2010-03-27 08:14:30