2010-12-15 76 views
6
lst = [1,2,3,4,1] 

我想知道1在此列表中出現兩次,是否有任何有效的方法?Python:根據值檢查列表中的出現次數

+1

你的問題有點模糊(或者也許太具體)。你是否在尋找任何,全部或第一個不是唯一的列表?任何發生超過一次的事情?事實上,1是名單中的第一件重要的事情?解釋爲什麼你想知道這可能也有幫助。 – martineau 2010-12-15 09:29:26

回答

26

lst.count(1)會返回它發生的次數。如果你打算列表中的項目,O(n)就是你將要得到的。

列表上的一般功能是list.count(x),並且將返回在列表中發生的次數x

+0

+1 - 太快:) – 2010-12-15 03:20:49

11

你問清單中的每一件物品是否都是唯一的?

len(set(lst)) == len(lst) 

是否1發生多次?

lst.count(1) > 1 

注意,上面是不是最高效的,因爲它不會短路 - 即使1出現兩次,它仍然會算髮生的其餘部分。如果你想讓它短路,你將不得不寫一些更復雜的東西。

第一個元素是否出現多次?

lst[0] in lst[1:] 

每個元素出現的頻率?

import collections 
collections.Counter(lst) 

還有其他嗎?

+1

+1對於collections.Counter和一些好的想法。切片製作整個列表的副本。使用itertools.islice(lst,1,None)只會遍歷它並發現短路。 – kevpie 2010-12-15 03:41:16

1
def valCount(lst): 
    res = {} 
    for v in lst: 
     try: 
      res[v] += 1 
     except KeyError: 
      res[v] = 1 
    return res 

u = [ x for x,y in valCount(lst).iteritems() if y > 1 ] 

u現在是所有值出現多次的列表。

編輯:

@katrielalex:謝謝你指出collections.Counter,而我以前沒有意識到。它也可以使用collections.defaultdict更簡潔地編寫,如以下測試中所演示的。這三種方法大致都是O(n),並且在運行時性能上相當接近(使用collections.defaultdict實際上比collections.Counter稍快)。

我的意圖是對似乎相對不成熟的請求給出一個易於理解的迴應。鑑於此,是否還有其他感覺,認爲它是「糟糕的代碼」或「做得不好」?

import collections 
import random 
import time 

def test1(lst): 
    res = {} 
    for v in lst: 
     try: 
      res[v] += 1 
     except KeyError: 
      res[v] = 1 
    return res 

def test2(lst): 
    res = collections.defaultdict(lambda: 0) 
    for v in lst: 
     res[v] += 1 
    return res 

def test3(lst): 
    return collections.Counter(lst) 

def rndLst(lstLen): 
    r = random.randint 
    return [r(0,lstLen) for i in xrange(lstLen)] 

def timeFn(fn, *args): 
    st = time.clock() 
    res = fn(*args) 
    return time.clock() - st 

def main(): 
    reps = 5000 

    res = [] 
    tests = [test1, test2, test3] 

    for t in xrange(reps): 
     lstLen = random.randint(10,50000) 
     lst = rndLst(lstLen) 
     res.append([lstLen] + [timeFn(fn, lst) for fn in tests]) 

    res.sort() 
    return res 

並且結果,對於包含多達50000項隨機列表,如下: (垂直軸是時間(秒),橫軸是在列表中的項目的數目) alt text

+1

這是不好的代碼:你不僅複製'collections.Counter',你做得不好。 – katrielalex 2010-12-15 03:34:08

+0

-1除外。 – 2010-12-15 03:57:24

0

的另一種方式吃出出現一次以上的所有項目:

lst = [1,2,3,4,1] 
d = {} 
for x in lst: 
    d[x] = x in d 
print d[1] # True 
print d[2] # False 
print [x for x in d if d[x]] # [1] 
1

爲多發,這給你每種情況的指標:

>>> lst=[1,2,3,4,5,1] 
>>> tgt=1 
>>> found=[] 
>>> for index, suspect in enumerate(lst): 
...  if(tgt==suspect): 
...  found.append(index) 
... 
>>> print len(found), "found at index:",", ".join(map(str,found)) 
2 found at index: 0, 5 

如果希望每個項目在列表中的計數:

>>> lst=[1,2,3,4,5,2,2,1,5,5,5,5,6] 
>>> count={} 
>>> for item in lst: 
...  count[item]=lst.count(item) 
... 
>>> count 
{1: 2, 2: 3, 3: 1, 4: 1, 5: 5, 6: 1} 
0

您也可以對列表進行排序是O(N *的log(n)),然後檢查相鄰的元素平等,這是O(n)。結果是O(n * log(n))。這有一個缺點,就是要求在發現重複數據時可能要保釋的情況下對整個列表進行排序。

對於一個相對罕見的重複列表的大列表,這可能是關於你可以做的最好的。處理這個問題的最好方法確實取決於所涉及的數據的大小及其性質。