簡體   English   中英

確定Python列表是否相同95%?

[英]Determine if a Python list is 95% the same?

這個問題詢問如何確定列表中的每個元素是否相同。 我如何以合理有效的方式確定列表中95%的元素是否相同? 例如:

>>> ninety_five_same([1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1])
True
>>> ninety_five_same([1,1,1,1,1,1,2,1]) # only 80% the same
False

這需要有些效率,因為列表可能非常大。

>>> from collections import Counter
>>> lst = [1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
>>> _, freq = Counter(lst).most_common(1)[0]
>>> len(lst)*.95 <= freq
True

實際上,對於類似的問題,有一個簡單的線性解決方案,只有50%的約束而不是95%。 檢查這個問題 ,它只是幾行代碼。

它也適用於你,最后你只檢查所選元素是否滿足95%的閾值,而不是50%。 (盡管如Thilo所說,如果currentCount >= n*0.95則沒有必要。)

我還將從st0le的回答中發布Python代碼,向大家展示它有多難。

currentCount = 0
currentValue = lst[0]
for val in lst:
   if val == currentValue:
      currentCount += 1
   else:
      currentCount -= 1

   if currentCount == 0:
      currentValue = val
      currentCount = 1

如果您正在尋找解釋,我認為Nabb已經得到了最好的解釋。

def ninety_five_same(lst):
    freq = collections.defaultdict(int)
    for x in lst:
        freq[x] += 1
    freqsort = sorted(freq.itervalues())
    return freqsort[-1] >= .95 * sum(freqsort)

假設完美的哈希表性能和良好的排序算法,這在O( n + m lg m )中運行,其中m是不同項的數量。 O( n lg n )最壞的情況。

編輯 :這是一個O( n + m ),單通道版本(假設m << n ):

def ninety_five_same(lst):
    freq = collections.defaultdict(int)
    for x in lst:
        freq[x] += 1
    freq = freq.values()
    return max(freq) >= .95 * sum(freq)

內存使用是O( m )。 maxsum可以用單個循環代替。

這比檢查每個元素是否相同效率更低。

該算法大致相同,遍歷列表中的每個元素並計算那些與預期的元素不匹配的元素(更難以知道哪一個是預期的元素)。 但是,這次,當你遇到第一個不匹配時,你不能只返回false,你必須繼續,直到你有足夠的不匹配來彌補5%的錯誤率。

想一想,弄清楚哪個元素是“正確的”可能並不那么容易,並且需要計算每個值,直到可以確定5%是錯位的。

考慮一個包含10.000個元素的列表,其中99%是42個:

  (1,2,3,4,5,6,7,8,9,10, ... , 100, 42,42, 42, 42 .... 42)

所以我認為你必須開始為表格的前5%建立一個頻率表。

def ninety_five_same(l):
  return max([l.count(i) for i in set(l)])*20 >= 19*len(l)

同時消除浮動分割精度的問題。

把你的名單想象成一桶紅色和黑色的球。

如果你在一個十個球的桶中有一個紅球,你隨機挑選一個球並將其放回桶中,然后重復一次采樣和替換步驟,一千次中有多少次你希望平均觀察到一個紅球?

查看二項分布並檢查置信區間 如果你有一個很長的清單,並希望相對有效地做事,那么采樣就是最佳選擇。

lst = [1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
#lst = [1, 2, 1, 4, 1]
#lst = [1, 2, 1, 4]

length = len(lst)
currentValue = lst[0]
lst.pop(0)
currentCount = 1

for val in lst:
   if currentCount == 0:
      currentValue = val

   if val == currentValue:
      currentCount += 1
   else:
      currentCount -= 1

percent = (currentCount * 50.0 / length + 50)
epsilon = 0.1
if (percent - 50 > epsilon):
    print "Percent %g%%" % percent
else:
    print "No majority"

注意:epsilon有一個“隨機”值,根據數組的長度選擇一些東西.Nikita Rybak的currentCount >= n*0.95的解決方案不起作用,因為currentCount的值根據元素的順序而不同,但是以上確實有效

C:\Temp>a.py
[2, 1, 1, 4, 1]
currentCount = 1

C:\Temp>a.py
[1, 2, 1, 4, 1]
currentCount = 2

排序作為一般解決方案可能很重,但考慮Python中的tim排序的非常均衡的性質,它利用列表的現有順序。 我建議對列表進行排序(或者使用已排序的副本,但該副本會損害性能)。 從末端和前面掃描以找到相同的元素或達到掃描長度> 5%,否則列表與找到的元素的95%相似。

將隨機元素作為候選元素並通過降低頻率順序來計算它們可能也不會那么糟糕,直到發現計數> 95%或總計數超過5%。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM