3

リスト内の2つの要素がまったく同じであるかどうかを判断する最も効率的な方法は何ですか?例えば:

>>> has1dup(["one", "one", "two"])
True
>>> has1dup(["one", "two", "three"])
False
>>> has1dup(["one", "one", "one"])
False

if/elseステートメントを使用してこれを正常に実行しました。ただし、リストが大きい場合、ペアの各可能性を書き出す作業は非常に困難で時間がかかります。これを達成するためのより速く/より簡単な方法はありますか?

これが私が試したことです:

def has1dup(lst):
    if lst[0] == lst[1] and lst[1] != lst[2]:
        return True
    elif lst[1] == lst[2] and lst[2] != lst[0]:
        return True
    elif lst[0] == lst[2] and lst[2] != lst[1]:
        return True
    else:
        return False
4

12 に答える 12

11

を使用すると、一意の値がいくつあるかを確認できますset。セット内のアイテムがリストよりも1つ少ない場合、1つは重複しています。

def has1dup(lst):
    return len(lst)-1 == len(set(lst))
于 2012-04-27T01:04:22.550 に答える
3
>>> from collection import Counter
>>> 2 in Counter(["one", "one", "two"]).values()
True
>>> 2 in Counter(["one", "two", "three"]).values()
False

更新
したい場合は同じアイテムが2つだけあります

Counter(seq).values().count(2) == 1

Python 2.7以降でCounter動作しますが、下位バージョンでは手動で実行できます

def counter(seq): 
    r = {}
    for x in seq:
        r[x] = r.setdefault(x, 0) + 1 # or defaultdict
    return r
于 2012-04-27T01:15:48.287 に答える
2

ビルトインを使用するany()と、これを非常に簡単かつうまく行うことができます:

def has_duplicates(seq):
    return any(seq.count(x) > 1 for x in seq)

例:

>>> has_duplicates([1, 1, 2])
True
>>> has_duplicates([1, 2, 2])
True
>>> has_duplicates([1, 2, 3])
False

2つだけのアイテムが同じである場所だけを見つけたい場合は、条件を変更するだけです。

any(seq.count(x) == 2 for x in seq)

1つ、2つのインスタンスが1つ、アイテムが2つしかない場所を見つけたい場合は、さらに作業が必要ですが、それも可能です。

def any_n(iterable, n):
    seen = 0
    for value in iterable:
        if value:
            if seen >= n:
                return False
            else:
                seen += 1
    return seen == n

def has_one_value_repeated_n_times(seq, n):
    return any_n((seq.count(x) == n for x in seq), n)

いくつかの簡単なテスト:

tests = [
    [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5],
    [1,2,2,3,3,4,4,4,4,5,5,5,5,5],
    [1,2,2],
    [1,1,2],
    [1,2,3],
]

for test in tests:
    print(test, "-", has_one_value_repeated_n_times(test, 2))

私たちに与える:

[1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5] - True
[1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5] - False
[1, 2, 2] - True
[1, 1, 2] - True
[1, 2, 3] - False
于 2012-04-27T01:15:48.340 に答える
1
2 in collections.Counter(yourList).values()

短くて効率的。

「要素の多重度の中に、多重度2の要素が1つだけある」のように「正確に」を意味する場合は、次のようにします。

Counter(Counter(yourList).values()).get(2)==1
于 2012-04-27T01:16:44.933 に答える
0

Pythonはわかりませんが、次のような擬似コードがあります。

for i in 0 to length(list):
    j = indexOf(list, list[i], i + 1) > -1

    if j > -1 and indexOf(list, list[i], j + 1) == -1:
        // Found exactly two!

それはあなたのニーズに対して十分に効率的でなければなりません。

編集:さて、私はそれをPythonに変えました。良いコードではない場合は申し訳ありません。

def exactlyTwo(l):
    for i in xrange(0, len(l)):
        try:
            j = l.index(l[i], i + 1)

            try:
                l.index(l[i], j + 1)
            except ValueError:
                return True
        except ValueError:
            # Do nothing. Not sure how to do that in Python.
            0

    return False

これがデモです。

于 2012-04-27T01:03:38.853 に答える
0

私はこれを試してみます:len(set(my_list)) == 2

しかし、それが機能するケース(3項目)では、はるかにうまくいくことがわかります。 > python -c 'from timeit import Timer; t1 = Timer("a[0] == a[1] != a[2] or a[0] == a[2] != a[1] or a[1] == a[2] != a[0]", setup="""a=["one","one","two"]"""); t2 = Timer("len(set(a)) == 2", setup="""a=["one","one","two"]"""); print t1.timeit(), t2.timeit()'

0.893960952759 2.28438997269

于 2012-04-27T01:04:43.143 に答える
0

あなたが持っているコードには何も問題はありません(少なくともサイズ3のリストの場合)-それは読みやすく、かなり簡潔であり、問​​題が発生した場合にのみパフォーマンスについて心配する必要があります。

セット変換のようなソリューションが3つの条件文よりもはるかに高速である可能性は、不可能ではありませんが、ありそうにありません。

「インデント地獄」を減らすために、少し異なる形式を好みます:-)

if list[0] == list[1] and list[1] != list[2]:
    return True

if list[1] == list[2] and list[2] != list[0]:
    return True

if list[0] == list[2] and list[2] != list[1]:
    return True

return False

または、画面/プリントアウトに一度に同じ数のコードを表示したい場合は、次のようにします。

if list[0] == list[1] and list[1] != list[2]: return True
if list[1] == list[2] and list[2] != list[0]: return True
if list[0] == list[2] and list[2] != list[1]: return True
return False

より大きな配列の場合、それをセットに変換できます。セットの長さが配列の長さより1つ短い場合は、重複が1つだけあります。

>>> a = [1,2,3,4,4,5,6,7]
>>> a
[1, 2, 3, 4, 4, 5, 6, 7]
>>> len(a) == len (set(a)) + 1
True
于 2012-04-27T01:05:30.990 に答える
0

要素が1つだけ/まったく繰り返されておらず、要素を正の整数として表すことができる場合(たとえば、dictを使用して「1」を1にマッピングすることにより)

次に、次の解決策が機能します

def find_repeated_element(l):
    return reduce(lambda x,y: x^y, l + list(set(l)))

l = [1,1,2]
>>> find_repeated_element(l)
1
l = [1,2,3]
>>> find_repeated_element(l)
0
l = [1,1,1]
>>> find_repeated_element(l)
0
于 2012-04-27T01:21:23.230 に答える
0

ペアワイズ比較を行う必要があるのでitertools.product、すべてのペア比較のシーケンスを作成するために使用してはどうでしょうか。

from itertools import product

tests = """\
AAB
ABC
ABB
ABA
AAA""".splitlines()

def has_exactly_one_doubled_element(t):
    return sum(map(lambda a:a[0]==a[1], product(t,t))) == 5

for t in tests:
    print t, has_exactly_one_doubled_element(t)

プリント:

AAB True
ABC False
ABB True
ABA True
AAA False

では、どうやって魔法の数5を思いついたのでしょうか。productによって返されるペアは、リストの2番目のコピーの要素とペアになっている各要素です。3つすべてが異なる場合、それぞれが同等であると比較されますが、他は同等ではないため、合計は3になります。2つが同じである場合、3つの一致に加えて、2つの複製は1回互いに同等に比較されます。各方向で、2を3に加算して5を取得します。3つすべてが同じ場合、各要素は他のすべての要素と一致し、3*3または9の一致になります。

重複する値が1つだけあるかどうかを確認するために、任意の長さのリストの一般的な解決策を次に示します(また、ラムダをに渡さないように使用operator.__eq__します)。itertools.starmapmap

from operator import __eq__ as EQ
from itertools import product, starmap

def has_exactly_one_doubled_element(t):
    return sum(starmap(EQ, product(t,t))) == len(t)+2

args = ["ABCD"]*4
tests = map(''.join, product(*args))
for t in tests:
    print t, has_exactly_one_doubled_element(t)

プリント:

AAAA False
AAAB False
AAAC False
AAAD False
AABA False
AABB False
AABC True
AABD True
AACA False
AACB True
AACC False
AACD True
AADA False
AADB True
AADC True
AADD False
ABAA False
ABAB False
ABAC True
ABAD True
ABBA False
ABBB False
ABBC True
ABBD True
ABCA True
ABCB True
ABCC True
ABCD False
ABDA True
ABDB True
ABDC False
ABDD True
ACAA False
ACAB True
ACAC False
ACAD True
ACBA True
ACBB True
ACBC True
ACBD False
ACCA False
ACCB True
ACCC False
ACCD True
ACDA True
ACDB False
ACDC True
ACDD True
ADAA False
ADAB True
ADAC True
ADAD False
ADBA True
ADBB True
ADBC False
ADBD True
ADCA True
ADCB False
ADCC True
ADCD True
ADDA False
ADDB True
ADDC True
ADDD False
BAAA False
BAAB False
BAAC True
BAAD True
BABA False
BABB False
BABC True
BABD True
BACA True
BACB True
BACC True
BACD False
BADA True
BADB True
BADC False
BADD True
BBAA False
BBAB False
BBAC True
BBAD True
BBBA False
BBBB False
BBBC False
BBBD False
BBCA True
BBCB False
BBCC False
BBCD True
BBDA True
BBDB False
BBDC True
BBDD False
BCAA True
BCAB True
BCAC True
BCAD False
BCBA True
BCBB False
BCBC False
BCBD True
BCCA True
BCCB False
BCCC False
BCCD True
BCDA False
BCDB True
BCDC True
BCDD True
BDAA True
BDAB True
BDAC False
BDAD True
BDBA True
BDBB False
BDBC True
BDBD False
BDCA False
BDCB True
BDCC True
BDCD True
BDDA True
BDDB False
BDDC True
BDDD False
CAAA False
CAAB True
CAAC False
CAAD True
CABA True
CABB True
CABC True
CABD False
CACA False
CACB True
CACC False
CACD True
CADA True
CADB False
CADC True
CADD True
CBAA True
CBAB True
CBAC True
CBAD False
CBBA True
CBBB False
CBBC False
CBBD True
CBCA True
CBCB False
CBCC False
CBCD True
CBDA False
CBDB True
CBDC True
CBDD True
CCAA False
CCAB True
CCAC False
CCAD True
CCBA True
CCBB False
CCBC False
CCBD True
CCCA False
CCCB False
CCCC False
CCCD False
CCDA True
CCDB True
CCDC False
CCDD False
CDAA True
CDAB False
CDAC True
CDAD True
CDBA False
CDBB True
CDBC True
CDBD True
CDCA True
CDCB True
CDCC False
CDCD False
CDDA True
CDDB True
CDDC False
CDDD False
DAAA False
DAAB True
DAAC True
DAAD False
DABA True
DABB True
DABC False
DABD True
DACA True
DACB False
DACC True
DACD True
DADA False
DADB True
DADC True
DADD False
DBAA True
DBAB True
DBAC False
DBAD True
DBBA True
DBBB False
DBBC True
DBBD False
DBCA False
DBCB True
DBCC True
DBCD True
DBDA True
DBDB False
DBDC True
DBDD False
DCAA True
DCAB False
DCAC True
DCAD True
DCBA False
DCBB True
DCBC True
DCBD True
DCCA True
DCCB True
DCCC False
DCCD False
DCDA True
DCDB True
DCDC False
DCDD False
DDAA False
DDAB True
DDAC True
DDAD False
DDBA True
DDBB False
DDBC True
DDBD False
DDCA True
DDCB True
DDCC False
DDCD False
DDDA False
DDDB False
DDDC False
DDDD False
于 2012-04-27T02:23:44.133 に答える
0
def exactlyTwo(elements):
    return sum(elements.count(i)-1 for i in elements) == 2

ハッシュできない要素に対して機能し、「正確に2つの要素」はトリプレットを意味し、2つのダブルはFalseを返す必要があります

于 2012-04-28T14:28:47.377 に答える
-1
def checkk(lis):
  sett=set(lis)
  for ele in sett:
     if lis.count(ele)==2:
       return 'yes'
  else:
     return 'no'


x=list(["one", "one", "two"])
y=list(["one", "two", "three"])
z=list(["one", "one", "one"])
w=list(["one", "two", "two"])
print(checkk(x))
print(checkk(y))
print(checkk(z))
print(checkk(w))

出力:

yes
no
no
yes
于 2012-04-27T01:05:58.180 に答える
-2

あなたは試すことができます

list(["one", "one", "two"]).count("one") == 2
于 2012-04-27T01:01:42.460 に答える