簡體   English   中英

在列表中找到與其他元素不同的元素的最pythonic方法是什么?

[英]what is most pythonic way to find a element in a list that is different with other elements?

假設我們有一個大小未知的列表,列表中有一個元素與其他元素不同,但我們不知道元素的索引。 該列表僅包含數字並從遠程服務器獲取,並且每次更改列表的長度和不同元素的索引。 什么是找到不同元素的最pythonic方式? 我嘗試了這個,但我不確定它是否是最好的解決方案。

a = 1
different_element = None
my_list = fetch_list()

b = my_list[0] - a

for elem in my_list[1::]:
    if elem - a != b:
        different_element = elem

print(different_element)

這對你有用嗎?

In [6]: my_list = [1,1,1,2,1,1,1]
In [7]: different = [ii for ii in set(my_list) if my_list.count(ii) == 1]
In [8]: different
Out[8]: [2]

您可以使用Counter from collections

from collections import Counter

a = [1,2,3,4,3,4,1]
b = Counter(a)  # Counter({1: 2, 2: 1, 3: 2, 4: 2})
elem = list(b.keys())[list(b.values()).index(1)]  # getting elem which is key with value that equals 1
print(a.index(elem))

另一種可能的解決方案,只是不同的計算elem

a = [1,2,3,4,3,4,1]
b = Counter(a)  # Counter({1: 2, 2: 1, 3: 2, 4: 2})
elem = (k for k, v in b.items() if v == 1)
print(a.index(next(elem)))

UPDATE

時間消耗:

正如@Jblasco所說,Jblasco的方法並不是真正有效的方法,我很想測量它。

因此,初始數據是具有200-400個元素的數組,只有一個唯一值。 生成該數組的代碼是。 在剪切結束時,有100個第一個元素證明它有一個獨特的元素

import random
from itertools import chain
f = lambda x: [x]*random.randint(2,4)
a=list(chain.from_iterable(f(random.randint(0,100)) for _ in range(100)))
a[random.randint(1, 100)] = 101
print(a[:100])
# [5, 5, 5, 84, 84, 84, 46, 46, 46, 46, 6, 6, 6, 68, 68, 68, 68, 38,
# 38, 38, 44, 44, 61, 61, 15, 15, 15, 15, 36, 36, 36, 36, 73, 73, 73, 
# 28, 28, 28, 28, 6, 6, 93, 93, 74, 74, 74, 74, 12, 12, 72, 72, 22, 
# 22, 22, 22, 78, 78, 17, 17, 17, 93, 93, 93, 12, 12, 12, 23, 23, 23, 
# 23, 52, 52, 88, 88, 79, 79, 42, 42, 34, 34, 47, 47, 1, 1, 1, 1, 71,
# 71, 1, 1, 45, 45, 101, 45, 39, 39, 50, 50, 50, 50]

這是向我們展示結果的代碼,我選擇執行3次10000次執行:

from timeit import repeat


s = """\
import random
from itertools import chain
f = lambda x: [x]*random.randint(2,4)
a=list(chain.from_iterable(f(random.randint(0,100)) for _ in range(100)))
a[random.randint(1, 100)] = 101
"""

print('my 1st method:', repeat(stmt="""from collections import Counter
b=Counter(a)
elem = (k for k, v in b.items() if v == 1)
a.index(next(elem))""",
             setup=s, number=10000, repeat=3)

print('my 2nd method:', repeat(stmt="""from collections import Counter
b = Counter(a)
elem = list(b.keys())[list(b.values()).index(1)]
a.index(elem)""",
             setup=s, number=10000, repeat=3))

print('@Jblasco method:', repeat(stmt="""different = [ii for ii in set(a) if a.count(ii) == 1]
different""", setup=s, number=10000, repeat=3))

# my 1st method: [0.303596693000145, 0.27322746600111714, 0.2701447969993751]
# my 2nd method: [0.2715420649983571, 0.28590541199810104, 0.2821485950007627]
# @Jblasco method: [3.2133491599997797, 3.488262927003234, 2.884892332000163]

這對於numpy來說非常有用

給定一些隨機統一列表,其中包含一個唯一不同的數字:

>>> li=[1]*100+[200]+[1]*250

如果統一值已知(在本例中為1且未知值為200),則可以使用np.where上的np.where來獲取該值:

>>> import numpy as np
>>> a=np.array(li)
>>> a[a!=1]
array([200])

如果統一值未知,則可以使用np.uniques來獲取唯一值的計數:

>>> np.unique(a, return_counts=True)
(array([  1, 200]), array([350,   1]))

對於純Python解決方案,使用帶有next的生成器獲取與所有其他值不同的第一個值:

>>> next(e for i, e in enumerate(li) if li[i]!=1)
200

或者,您可以使用itertools中的dropwhile

>>> from itertools import dropwhile
>>> next(dropwhile(lambda e: e==1, li))
200

如果您不知道統一值是什么,請在足夠大的切片上使用計數器來獲取它:

>>> uniform=Counter(li[0:3]).most_common()[0][0]
>>> uniform
1
>>> next(e for i, e in enumerate(li) if li[i]!=uniform)
200

在這些情況下, next將在滿足條件的第一個值處短路。

我會嘗試這樣的事情:

newList = list(set(my_list))
print newList.pop()

假設只有1個不同的值,其余的都是相同的。 你的問題中存在一些含糊不清的問題,這使我很難回答,但這是我能想到的最佳方案。

暫無
暫無

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

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