Bagaimana saya bisa menemukan duplikat dalam daftar Python dan membuat daftar duplikat lain? Daftar hanya berisi bilangan bulat.
Bagaimana saya bisa menemukan duplikat dalam daftar Python dan membuat daftar duplikat lain? Daftar hanya berisi bilangan bulat.
Jawaban:
Untuk menghapus duplikat gunakan set(a)
. Untuk mencetak duplikat, sesuatu seperti:
a = [1,2,3,2,1,5,6,5,5,5]
import collections
print([item for item, count in collections.Counter(a).items() if count > 1])
## [1, 2, 5]
Perhatikan bahwa Counter
ini tidak terlalu efisien ( timing ) dan mungkin berlebihan di sini. set
akan tampil lebih baik. Kode ini menghitung daftar elemen unik dalam urutan sumber:
seen = set()
uniq = []
for x in a:
if x not in seen:
uniq.append(x)
seen.add(x)
atau, lebih ringkas:
seen = set()
uniq = [x for x in a if x not in seen and not seen.add(x)]
Saya tidak merekomendasikan gaya yang terakhir, karena tidak jelas apa not seen.add(x)
yang dilakukan ( add()
metode yang ditetapkan selalu kembali None
, maka kebutuhan untuk not
).
Untuk menghitung daftar elemen yang digandakan tanpa pustaka:
seen = {}
dupes = []
for x in a:
if x not in seen:
seen[x] = 1
else:
if seen[x] == 1:
dupes.append(x)
seen[x] += 1
Jika elemen daftar tidak hashable, Anda tidak dapat menggunakan set / dicts dan harus menggunakan solusi waktu kuadratik (bandingkan masing-masing dengan masing-masing). Sebagai contoh:
a = [[1], [2], [3], [1], [5], [3]]
no_dupes = [x for n, x in enumerate(a) if x not in a[:n]]
print no_dupes # [[1], [2], [3], [5]]
dupes = [x for n, x in enumerate(a) if x in a[:n]]
print dupes # [[1], [3]]
O(n)
, karena hanya mengulangi daftar sekali dan mengatur pencarian O(1)
.
dup = []
else: dup.append(x)
print()
seen = set()
laludupe = set(x for x in a if x in seen or seen.add(x))
>>> l = [1,2,3,4,4,5,5,6,1]
>>> set([x for x in l if l.count(x) > 1])
set([1, 4, 5])
l
dengan set(l)
hanya mengurangi kompleksitas waktu terburuk dan karenanya tidak melakukan apa pun untuk mengatasi masalah efisiensi skala besar dengan jawaban ini. Mungkin itu tidak sesederhana itu. Singkatnya, jangan lakukan ini.
Anda tidak perlu menghitung, hanya apakah barang itu dilihat sebelumnya atau tidak. Diadaptasi jawaban itu untuk masalah ini:
def list_duplicates(seq):
seen = set()
seen_add = seen.add
# adds all elements it doesn't know yet to seen and all other to seen_twice
seen_twice = set( x for x in seq if x in seen or seen_add(x) )
# turn the set into a list (as requested)
return list( seen_twice )
a = [1,2,3,2,1,5,6,5,5,5]
list_duplicates(a) # yields [1, 2, 5]
Untuk berjaga-jaga soal kecepatan, berikut adalah beberapa timing:
# file: test.py
import collections
def thg435(l):
return [x for x, y in collections.Counter(l).items() if y > 1]
def moooeeeep(l):
seen = set()
seen_add = seen.add
# adds all elements it doesn't know yet to seen and all other to seen_twice
seen_twice = set( x for x in l if x in seen or seen_add(x) )
# turn the set into a list (as requested)
return list( seen_twice )
def RiteshKumar(l):
return list(set([x for x in l if l.count(x) > 1]))
def JohnLaRooy(L):
seen = set()
seen2 = set()
seen_add = seen.add
seen2_add = seen2.add
for item in L:
if item in seen:
seen2_add(item)
else:
seen_add(item)
return list(seen2)
l = [1,2,3,2,1,5,6,5,5,5]*100
Inilah hasilnya: (dilakukan dengan baik @JohnLaRooy!)
$ python -mtimeit -s 'import test' 'test.JohnLaRooy(test.l)'
10000 loops, best of 3: 74.6 usec per loop
$ python -mtimeit -s 'import test' 'test.moooeeeep(test.l)'
10000 loops, best of 3: 91.3 usec per loop
$ python -mtimeit -s 'import test' 'test.thg435(test.l)'
1000 loops, best of 3: 266 usec per loop
$ python -mtimeit -s 'import test' 'test.RiteshKumar(test.l)'
100 loops, best of 3: 8.35 msec per loop
Menariknya, selain timing itu sendiri, peringkat juga sedikit berubah ketika pypy digunakan. Yang paling menarik, pendekatan berbasis-Counter mendapat manfaat besar dari optimasi pypy, sedangkan metode caching yang saya sarankan tampaknya hampir tidak berpengaruh.
$ pypy -mtimeit -s 'import test' 'test.JohnLaRooy(test.l)'
100000 loops, best of 3: 17.8 usec per loop
$ pypy -mtimeit -s 'import test' 'test.thg435(test.l)'
10000 loops, best of 3: 23 usec per loop
$ pypy -mtimeit -s 'import test' 'test.moooeeeep(test.l)'
10000 loops, best of 3: 39.3 usec per loop
Tampaknya efek ini terkait dengan "duplikasi" dari data input. Saya telah menetapkan l = [random.randrange(1000000) for i in xrange(10000)]
dan mendapatkan hasil ini:
$ pypy -mtimeit -s 'import test' 'test.moooeeeep(test.l)'
1000 loops, best of 3: 495 usec per loop
$ pypy -mtimeit -s 'import test' 'test.JohnLaRooy(test.l)'
1000 loops, best of 3: 499 usec per loop
$ pypy -mtimeit -s 'import test' 'test.thg435(test.l)'
1000 loops, best of 3: 1.68 msec per loop
add
setiap kali memasukkan akan diperlukan.
pypy
jika Anda memilikinya dan akan mempercepat.
Anda bisa menggunakan iteration_utilities.duplicates
:
>>> from iteration_utilities import duplicates
>>> list(duplicates([1,1,2,1,2,3,4,2]))
[1, 1, 2, 2]
atau jika Anda hanya menginginkan satu dari setiap duplikat ini dapat digabungkan dengan iteration_utilities.unique_everseen
:
>>> from iteration_utilities import unique_everseen
>>> list(unique_everseen(duplicates([1,1,2,1,2,3,4,2])))
[1, 2]
Ia juga dapat menangani elemen yang tidak dapat dihancurkan (namun dengan biaya kinerja):
>>> list(duplicates([[1], [2], [1], [3], [1]]))
[[1], [1]]
>>> list(unique_everseen(duplicates([[1], [2], [1], [3], [1]])))
[[1]]
Itu adalah sesuatu yang hanya bisa dilakukan oleh beberapa pendekatan lain di sini.
Saya melakukan patokan cepat yang mengandung sebagian besar (tetapi tidak semua) pendekatan yang disebutkan di sini.
Tolok ukur pertama hanya mencakup sejumlah kecil daftar panjang karena beberapa pendekatan memiliki O(n**2)
perilaku.
Dalam grafik, sumbu y mewakili waktu, sehingga nilai yang lebih rendah berarti lebih baik. Itu juga diplot log-log sehingga berbagai nilai dapat divisualisasikan dengan lebih baik:
Menghapus O(n**2)
pendekatan saya lakukan tolok ukur lain hingga setengah juta elemen dalam daftar:
Seperti yang Anda lihat, iteration_utilities.duplicates
pendekatannya lebih cepat daripada pendekatan lain mana pun dan bahkan rantai unique_everseen(duplicates(...))
lebih cepat atau sama cepatnya daripada pendekatan lainnya.
Satu hal tambahan yang menarik untuk dicatat di sini adalah bahwa pendekatan panda sangat lambat untuk daftar kecil tetapi dapat dengan mudah bersaing untuk daftar yang lebih panjang.
Namun karena tolok ukur ini menunjukkan sebagian besar pendekatan melakukan kurang lebih sama, sehingga tidak masalah banyak yang digunakan (kecuali untuk 3 yang memiliki O(n**2)
runtime).
from iteration_utilities import duplicates, unique_everseen
from collections import Counter
import pandas as pd
import itertools
def georg_counter(it):
return [item for item, count in Counter(it).items() if count > 1]
def georg_set(it):
seen = set()
uniq = []
for x in it:
if x not in seen:
uniq.append(x)
seen.add(x)
def georg_set2(it):
seen = set()
return [x for x in it if x not in seen and not seen.add(x)]
def georg_set3(it):
seen = {}
dupes = []
for x in it:
if x not in seen:
seen[x] = 1
else:
if seen[x] == 1:
dupes.append(x)
seen[x] += 1
def RiteshKumar_count(l):
return set([x for x in l if l.count(x) > 1])
def moooeeeep(seq):
seen = set()
seen_add = seen.add
# adds all elements it doesn't know yet to seen and all other to seen_twice
seen_twice = set( x for x in seq if x in seen or seen_add(x) )
# turn the set into a list (as requested)
return list( seen_twice )
def F1Rumors_implementation(c):
a, b = itertools.tee(sorted(c))
next(b, None)
r = None
for k, g in zip(a, b):
if k != g: continue
if k != r:
yield k
r = k
def F1Rumors(c):
return list(F1Rumors_implementation(c))
def Edward(a):
d = {}
for elem in a:
if elem in d:
d[elem] += 1
else:
d[elem] = 1
return [x for x, y in d.items() if y > 1]
def wordsmith(a):
return pd.Series(a)[pd.Series(a).duplicated()].values
def NikhilPrabhu(li):
li = li.copy()
for x in set(li):
li.remove(x)
return list(set(li))
def firelynx(a):
vc = pd.Series(a).value_counts()
return vc[vc > 1].index.tolist()
def HenryDev(myList):
newList = set()
for i in myList:
if myList.count(i) >= 2:
newList.add(i)
return list(newList)
def yota(number_lst):
seen_set = set()
duplicate_set = set(x for x in number_lst if x in seen_set or seen_set.add(x))
return seen_set - duplicate_set
def IgorVishnevskiy(l):
s=set(l)
d=[]
for x in l:
if x in s:
s.remove(x)
else:
d.append(x)
return d
def it_duplicates(l):
return list(duplicates(l))
def it_unique_duplicates(l):
return list(unique_everseen(duplicates(l)))
from simple_benchmark import benchmark
import random
funcs = [
georg_counter, georg_set, georg_set2, georg_set3, RiteshKumar_count, moooeeeep,
F1Rumors, Edward, wordsmith, NikhilPrabhu, firelynx,
HenryDev, yota, IgorVishnevskiy, it_duplicates, it_unique_duplicates
]
args = {2**i: [random.randint(0, 2**(i-1)) for _ in range(2**i)] for i in range(2, 12)}
b = benchmark(funcs, args, 'list size')
b.plot()
funcs = [
georg_counter, georg_set, georg_set2, georg_set3, moooeeeep,
F1Rumors, Edward, wordsmith, firelynx,
yota, IgorVishnevskiy, it_duplicates, it_unique_duplicates
]
args = {2**i: [random.randint(0, 2**(i-1)) for _ in range(2**i)] for i in range(2, 20)}
b = benchmark(funcs, args, 'list size')
b.plot()
1 ini adalah dari pihak ketiga perpustakaan saya telah menulis: iteration_utilities
.
Saya menemukan pertanyaan ini sambil mencari sesuatu yang berhubungan - dan bertanya-tanya mengapa tidak ada yang menawarkan solusi berbasis generator? Memecahkan masalah ini adalah:
>>> print list(getDupes_9([1,2,3,2,1,5,6,5,5,5]))
[1, 2, 5]
Saya prihatin dengan skalabilitas, jadi menguji beberapa pendekatan, termasuk item naif yang bekerja dengan baik pada daftar kecil, tetapi skala mengerikan ketika daftar menjadi lebih besar (catatan - akan lebih baik menggunakan timeit, tetapi ini ilustrasi).
Saya menyertakan @ mooooeeeep untuk perbandingan (sangat cepat: tercepat jika daftar input benar-benar acak) dan pendekatan itertools yang bahkan lebih cepat lagi untuk sebagian besar daftar yang diurutkan ... Sekarang termasuk pendekatan panda dari @firelynx - lambat, tetapi tidak begitu mengerikan, dan sederhana. Catatan - pendekatan sort / tee / zip secara konsisten tercepat di mesin saya untuk daftar yang sebagian besar dipesan, moooeeeep tercepat untuk daftar yang diacak, tetapi jarak tempuh Anda mungkin bervariasi.
Keuntungan
Asumsi
Solusi tercepat, entri 1m:
def getDupes(c):
'''sort/tee/izip'''
a, b = itertools.tee(sorted(c))
next(b, None)
r = None
for k, g in itertools.izip(a, b):
if k != g: continue
if k != r:
yield k
r = k
Pendekatan diuji
import itertools
import time
import random
def getDupes_1(c):
'''naive'''
for i in xrange(0, len(c)):
if c[i] in c[:i]:
yield c[i]
def getDupes_2(c):
'''set len change'''
s = set()
for i in c:
l = len(s)
s.add(i)
if len(s) == l:
yield i
def getDupes_3(c):
'''in dict'''
d = {}
for i in c:
if i in d:
if d[i]:
yield i
d[i] = False
else:
d[i] = True
def getDupes_4(c):
'''in set'''
s,r = set(),set()
for i in c:
if i not in s:
s.add(i)
elif i not in r:
r.add(i)
yield i
def getDupes_5(c):
'''sort/adjacent'''
c = sorted(c)
r = None
for i in xrange(1, len(c)):
if c[i] == c[i - 1]:
if c[i] != r:
yield c[i]
r = c[i]
def getDupes_6(c):
'''sort/groupby'''
def multiple(x):
try:
x.next()
x.next()
return True
except:
return False
for k, g in itertools.ifilter(lambda x: multiple(x[1]), itertools.groupby(sorted(c))):
yield k
def getDupes_7(c):
'''sort/zip'''
c = sorted(c)
r = None
for k, g in zip(c[:-1],c[1:]):
if k == g:
if k != r:
yield k
r = k
def getDupes_8(c):
'''sort/izip'''
c = sorted(c)
r = None
for k, g in itertools.izip(c[:-1],c[1:]):
if k == g:
if k != r:
yield k
r = k
def getDupes_9(c):
'''sort/tee/izip'''
a, b = itertools.tee(sorted(c))
next(b, None)
r = None
for k, g in itertools.izip(a, b):
if k != g: continue
if k != r:
yield k
r = k
def getDupes_a(l):
'''moooeeeep'''
seen = set()
seen_add = seen.add
# adds all elements it doesn't know yet to seen and all other to seen_twice
for x in l:
if x in seen or seen_add(x):
yield x
def getDupes_b(x):
'''iter*/sorted'''
x = sorted(x)
def _matches():
for k,g in itertools.izip(x[:-1],x[1:]):
if k == g:
yield k
for k, n in itertools.groupby(_matches()):
yield k
def getDupes_c(a):
'''pandas'''
import pandas as pd
vc = pd.Series(a).value_counts()
i = vc[vc > 1].index
for _ in i:
yield _
def hasDupes(fn,c):
try:
if fn(c).next(): return True # Found a dupe
except StopIteration:
pass
return False
def getDupes(fn,c):
return list(fn(c))
STABLE = True
if STABLE:
print 'Finding FIRST then ALL duplicates, single dupe of "nth" placed element in 1m element array'
else:
print 'Finding FIRST then ALL duplicates, single dupe of "n" included in randomised 1m element array'
for location in (50,250000,500000,750000,999999):
for test in (getDupes_2, getDupes_3, getDupes_4, getDupes_5, getDupes_6,
getDupes_8, getDupes_9, getDupes_a, getDupes_b, getDupes_c):
print 'Test %-15s:%10d - '%(test.__doc__ or test.__name__,location),
deltas = []
for FIRST in (True,False):
for i in xrange(0, 5):
c = range(0,1000000)
if STABLE:
c[0] = location
else:
c.append(location)
random.shuffle(c)
start = time.time()
if FIRST:
print '.' if location == test(c).next() else '!',
else:
print '.' if [location] == list(test(c)) else '!',
deltas.append(time.time()-start)
print ' -- %0.3f '%(sum(deltas)/len(deltas)),
print
print
Hasil untuk tes 'semua dupes' konsisten, menemukan duplikat "pertama" lalu duplikat "semua" dalam array ini:
Finding FIRST then ALL duplicates, single dupe of "nth" placed element in 1m element array
Test set len change : 500000 - . . . . . -- 0.264 . . . . . -- 0.402
Test in dict : 500000 - . . . . . -- 0.163 . . . . . -- 0.250
Test in set : 500000 - . . . . . -- 0.163 . . . . . -- 0.249
Test sort/adjacent : 500000 - . . . . . -- 0.159 . . . . . -- 0.229
Test sort/groupby : 500000 - . . . . . -- 0.860 . . . . . -- 1.286
Test sort/izip : 500000 - . . . . . -- 0.165 . . . . . -- 0.229
Test sort/tee/izip : 500000 - . . . . . -- 0.145 . . . . . -- 0.206 *
Test moooeeeep : 500000 - . . . . . -- 0.149 . . . . . -- 0.232
Test iter*/sorted : 500000 - . . . . . -- 0.160 . . . . . -- 0.221
Test pandas : 500000 - . . . . . -- 0.493 . . . . . -- 0.499
Ketika daftar dikocok terlebih dahulu, harga semacam itu menjadi jelas - efisiensinya turun secara nyata dan pendekatan @moooeeeep mendominasi, dengan pendekatan set & dict menjadi serupa tetapi berkinerja lebih rendah:
Finding FIRST then ALL duplicates, single dupe of "n" included in randomised 1m element array
Test set len change : 500000 - . . . . . -- 0.321 . . . . . -- 0.473
Test in dict : 500000 - . . . . . -- 0.285 . . . . . -- 0.360
Test in set : 500000 - . . . . . -- 0.309 . . . . . -- 0.365
Test sort/adjacent : 500000 - . . . . . -- 0.756 . . . . . -- 0.823
Test sort/groupby : 500000 - . . . . . -- 1.459 . . . . . -- 1.896
Test sort/izip : 500000 - . . . . . -- 0.786 . . . . . -- 0.845
Test sort/tee/izip : 500000 - . . . . . -- 0.743 . . . . . -- 0.804
Test moooeeeep : 500000 - . . . . . -- 0.234 . . . . . -- 0.311 *
Test iter*/sorted : 500000 - . . . . . -- 0.776 . . . . . -- 0.840
Test pandas : 500000 - . . . . . -- 0.539 . . . . . -- 0.540
random.shuffle(c)
memperhitungkannya. Selain itu saya tidak dapat mereplikasi hasil Anda ketika menjalankan skrip yang tidak diubah juga (pemesanan yang sama sekali berbeda), jadi mungkin itu tergantung pada CPU juga.
Menggunakan panda:
>>> import pandas as pd
>>> a = [1, 2, 1, 3, 3, 3, 0]
>>> pd.Series(a)[pd.Series(a).duplicated()].values
array([1, 3, 3])
collections.Counter baru di python 2.7:
Python 2.5.4 (r254:67916, May 31 2010, 15:03:39)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2
a = [1,2,3,2,1,5,6,5,5,5]
import collections
print [x for x, y in collections.Counter(a).items() if y > 1]
Type "help", "copyright", "credits" or "license" for more information.
File "", line 1, in
AttributeError: 'module' object has no attribute 'Counter'
>>>
Dalam versi sebelumnya, Anda dapat menggunakan dikt konvensional sebagai gantinya:
a = [1,2,3,2,1,5,6,5,5,5]
d = {}
for elem in a:
if elem in d:
d[elem] += 1
else:
d[elem] = 1
print [x for x, y in d.items() if y > 1]
Inilah solusi yang rapi dan ringkas -
for x in set(li):
li.remove(x)
li = list(set(li))
Tanpa mengkonversi ke daftar dan mungkin cara paling sederhana adalah seperti di bawah ini. Ini mungkin berguna selama wawancara ketika mereka meminta untuk tidak menggunakan set
a=[1,2,3,3,3]
dup=[]
for each in a:
if each not in dup:
dup.append(each)
print(dup)
======= lain untuk mendapatkan 2 daftar nilai unik dan nilai duplikat yang terpisah
a=[1,2,3,3,3]
uniques=[]
dups=[]
for each in a:
if each not in uniques:
uniques.append(each)
else:
dups.append(each)
print("Unique values are below:")
print(uniques)
print("Duplicate values are below:")
print(dups)
Saya akan melakukan ini dengan panda, karena saya sering menggunakan panda
import pandas as pd
a = [1,2,3,3,3,4,5,6,6,7]
vc = pd.Series(a).value_counts()
vc[vc > 1].index.tolist()
Memberi
[3,6]
Mungkin tidak terlalu efisien, tetapi pasti lebih sedikit kode daripada banyak jawaban lain, jadi saya pikir saya akan berkontribusi
pda = pd.Series(a)
print list(pda[pda.duplicated()])
contoh ketiga dari jawaban yang diterima memberikan jawaban yang salah dan tidak berusaha memberikan duplikat. Ini versi yang benar:
number_lst = [1, 1, 2, 3, 5, ...]
seen_set = set()
duplicate_set = set(x for x in number_lst if x in seen_set or seen_set.add(x))
unique_set = seen_set - duplicate_set
Bagaimana kalau hanya loop melalui setiap elemen dalam daftar dengan memeriksa jumlah kejadian, kemudian menambahkannya ke set yang kemudian akan mencetak duplikat. Semoga ini bisa membantu seseorang di luar sana.
myList = [2 ,4 , 6, 8, 4, 6, 12];
newList = set()
for i in myList:
if myList.count(i) >= 2:
newList.add(i)
print(list(newList))
## [4 , 6]
Kita dapat menggunakan itertools.groupby
untuk menemukan semua item yang memiliki dups:
from itertools import groupby
myList = [2, 4, 6, 8, 4, 6, 12]
# when the list is sorted, groupby groups by consecutive elements which are similar
for x, y in groupby(sorted(myList)):
# list(y) returns all the occurences of item x
if len(list(y)) > 1:
print x
Outputnya adalah:
4
6
dupes = [x for x, y in groupby(sorted(myList)) if len(list(y)) > 1]
Saya kira cara paling efektif untuk menemukan duplikat dalam daftar adalah:
from collections import Counter
def duplicates(values):
dups = Counter(values) - Counter(set(values))
return list(dups.keys())
print(duplicates([1,2,3,6,5,2]))
Ini menggunakan Counter
semua elemen dan semua elemen unik. Mengurangi yang pertama dengan yang kedua hanya akan meninggalkan duplikat.
Agak terlambat, tapi mungkin bermanfaat untuk beberapa. Untuk daftar yang lebih besar, saya menemukan ini bekerja untuk saya.
l=[1,2,3,5,4,1,3,1]
s=set(l)
d=[]
for x in l:
if x in s:
s.remove(x)
else:
d.append(x)
d
[1,3,1]
Menunjukkan keadilan dan semua duplikat serta menjaga ketertiban.
Cara yang sangat sederhana dan cepat untuk menemukan dupes dengan satu iterasi di Python adalah:
testList = ['red', 'blue', 'red', 'green', 'blue', 'blue']
testListDict = {}
for item in testList:
try:
testListDict[item] += 1
except:
testListDict[item] = 1
print testListDict
Outputnya adalah sebagai berikut:
>>> print testListDict
{'blue': 3, 'green': 1, 'red': 2}
Ini dan lebih banyak lagi di blog saya http://www.howtoprogramwithpython.com
Saya banyak terlambat masuk ke diskusi ini. Meskipun demikian, saya ingin menangani masalah ini dengan satu kalimat. Karena itulah pesona Python. jika kita hanya ingin mendapatkan duplikat ke daftar terpisah (atau koleksi apa pun), saya akan menyarankan untuk melakukan seperti di bawah ini. Katanya kita memiliki daftar duplikat yang dapat kita sebut sebagai 'target'
target=[1,2,3,4,4,4,3,5,6,8,4,3]
Sekarang jika kita ingin mendapatkan duplikat, kita dapat menggunakan satu liner seperti di bawah ini:
duplicates=dict(set((x,target.count(x)) for x in filter(lambda rec : target.count(rec)>1,target)))
Kode ini akan menempatkan catatan yang digandakan sebagai kunci dan menghitung sebagai nilai dalam kamus 'duplikat'. Kamus 'duplikat' akan terlihat seperti di bawah ini:
{3: 3, 4: 4} #it saying 3 is repeated 3 times and 4 is 4 times
Jika Anda hanya ingin semua catatan dengan duplikat saja dalam daftar, kode yang jauh lebih pendek:
duplicates=filter(lambda rec : target.count(rec)>1,target)
Output akan menjadi:
[3, 4, 4, 4, 3, 4, 3]
Ini berfungsi sempurna dalam versi python 2.7.x +
Python 3.8 one-liner jika Anda tidak ingin menulis algoritma Anda sendiri atau menggunakan pustaka:
l = [1,2,3,2,1,5,6,5,5,5]
res = [(x, count) for x, g in groupby(sorted(l)) if (count := len(list(g))) > 1]
print(res)
Mencetak item dan menghitung:
[(1, 2), (2, 2), (5, 4)]
groupby
mengambil fungsi pengelompokan sehingga Anda dapat menentukan pengelompokan Anda dengan cara yang berbeda dan mengembalikan Tuple
bidang tambahan sesuai kebutuhan.
groupby
malas jadi seharusnya tidak terlalu lambat.
Beberapa tes lain. Tentu saja ...
set([x for x in l if l.count(x) > 1])
... terlalu mahal. Ini sekitar 500 kali lebih cepat (array yang lebih panjang memberikan hasil yang lebih baik) untuk menggunakan metode terakhir berikut:
def dups_count_dict(l):
d = {}
for item in l:
if item not in d:
d[item] = 0
d[item] += 1
result_d = {key: val for key, val in d.iteritems() if val > 1}
return result_d.keys()
Hanya 2 loop, tidak ada l.count()
operasi yang sangat mahal .
Berikut ini adalah kode untuk membandingkan metode misalnya. Kode di bawah ini, ini adalah output:
dups_count: 13.368s # this is a function which uses l.count()
dups_count_dict: 0.014s # this is a final best function (of the 3 functions)
dups_count_counter: 0.024s # collections.Counter
Kode pengujian:
import numpy as np
from time import time
from collections import Counter
class TimerCounter(object):
def __init__(self):
self._time_sum = 0
def start(self):
self.time = time()
def stop(self):
self._time_sum += time() - self.time
def get_time_sum(self):
return self._time_sum
def dups_count(l):
return set([x for x in l if l.count(x) > 1])
def dups_count_dict(l):
d = {}
for item in l:
if item not in d:
d[item] = 0
d[item] += 1
result_d = {key: val for key, val in d.iteritems() if val > 1}
return result_d.keys()
def dups_counter(l):
counter = Counter(l)
result_d = {key: val for key, val in counter.iteritems() if val > 1}
return result_d.keys()
def gen_array():
np.random.seed(17)
return list(np.random.randint(0, 5000, 10000))
def assert_equal_results(*results):
primary_result = results[0]
other_results = results[1:]
for other_result in other_results:
assert set(primary_result) == set(other_result) and len(primary_result) == len(other_result)
if __name__ == '__main__':
dups_count_time = TimerCounter()
dups_count_dict_time = TimerCounter()
dups_count_counter = TimerCounter()
l = gen_array()
for i in range(3):
dups_count_time.start()
result1 = dups_count(l)
dups_count_time.stop()
dups_count_dict_time.start()
result2 = dups_count_dict(l)
dups_count_dict_time.stop()
dups_count_counter.start()
result3 = dups_counter(l)
dups_count_counter.stop()
assert_equal_results(result1, result2, result3)
print 'dups_count: %.3f' % dups_count_time.get_time_sum()
print 'dups_count_dict: %.3f' % dups_count_dict_time.get_time_sum()
print 'dups_count_counter: %.3f' % dups_count_counter.get_time_sum()
Metode 1:
list(set([val for idx, val in enumerate(input_list) if val in input_list[idx+1:]]))
Penjelasan: [val untuk idx, val in enumerate (input_list) jika val di input_list [idx + 1:]] adalah pemahaman daftar, yang mengembalikan elemen, jika elemen yang sama hadir dari posisi saat ini, dalam daftar, indeks .
Contoh: input_list = [42,31,42,31,3,31,31,5,6,6,6,6,6,7,42]
dimulai dengan elemen pertama dalam daftar, 42, dengan indeks 0, memeriksa apakah elemen 42, ada di input_list [1:] (yaitu, dari indeks 1 hingga akhir daftar) Karena 42 ada di input_list [1:] , itu akan mengembalikan 42.
Kemudian ia pergi ke elemen 31 berikutnya, dengan indeks 1, dan memeriksa apakah elemen 31 ada di input_list [2:] (yaitu, dari indeks 2 hingga akhir daftar), Karena 31 ada di input_list [2:], itu akan mengembalikan 31.
sama halnya ia menelusuri semua elemen dalam daftar, dan hanya akan mengembalikan elemen berulang / duplikat ke dalam daftar.
Kemudian karena kita memiliki duplikat, dalam daftar, kita perlu memilih satu dari setiap duplikat, yaitu menghapus duplikat di antara duplikat, dan untuk melakukannya, kita memanggil python built-in set bernama (), dan menghapus duplikat,
Kemudian kita dibiarkan dengan satu set, tetapi bukan daftar, dan karenanya untuk mengkonversi dari satu set ke daftar, kita menggunakan, typecasting, list (), dan yang mengubah set elemen ke daftar.
Metode 2:
def dupes(ilist):
temp_list = [] # initially, empty temporary list
dupe_list = [] # initially, empty duplicate list
for each in ilist:
if each in temp_list: # Found a Duplicate element
if not each in dupe_list: # Avoid duplicate elements in dupe_list
dupe_list.append(each) # Add duplicate element to dupe_list
else:
temp_list.append(each) # Add a new (non-duplicate) to temp_list
return dupe_list
Penjelasan: Di sini Kami membuat dua daftar kosong, untuk memulai. Lalu teruslah menelusuri semua elemen daftar, untuk melihat apakah ada di temp_list (awalnya kosong). Jika tidak ada di temp_list, maka kami menambahkannya ke temp_list, menggunakan metode append .
Jika sudah ada di temp_list, itu berarti, elemen daftar saat ini adalah duplikat, dan karenanya kita perlu menambahkannya ke dupe_list menggunakan metode append .
raw_list = [1,2,3,3,4,5,6,6,7,2,3,4,2,3,4,1,3,4,]
clean_list = list(set(raw_list))
duplicated_items = []
for item in raw_list:
try:
clean_list.remove(item)
except ValueError:
duplicated_items.append(item)
print(duplicated_items)
# [3, 6, 2, 3, 4, 2, 3, 4, 1, 3, 4]
Anda pada dasarnya menghapus duplikat dengan mengonversi ke set ( clean_list
), lalu iterasi raw_list
, sambil menghapus masing-masing item
dalam daftar bersih untuk terjadinya di raw_list
. Jika item
tidak ditemukan, ValueError
Pengecualian yang diangkat ditangkap dan item
ditambahkan ke duplicated_items
daftar.
Jika indeks item duplikat diperlukan, cukup enumerate
daftar dan mainkan dengan indeks. ( for index, item in enumerate(raw_list):
) yang lebih cepat dan dioptimalkan untuk daftar besar (seperti ribuan + elemen)
penggunaan list.count()
metode dalam daftar untuk mengetahui elemen duplikat dari daftar yang diberikan
arr=[]
dup =[]
for i in range(int(input("Enter range of list: "))):
arr.append(int(input("Enter Element in a list: ")))
for i in arr:
if arr.count(i)>1 and i not in dup:
dup.append(i)
print(dup)
list2 = [1, 2, 3, 4, 1, 2, 3]
lset = set()
[(lset.add(item), list2.append(item))
for item in list2 if item not in lset]
print list(lset)
Ada banyak jawaban di sini, tapi saya pikir ini relatif sangat mudah dibaca dan mudah dipahami:
def get_duplicates(sorted_list):
duplicates = []
last = sorted_list[0]
for x in sorted_list[1:]:
if x == last:
duplicates.append(x)
last = x
return set(duplicates)
Catatan:
Berikut adalah generator cepat yang menggunakan dict untuk menyimpan setiap elemen sebagai kunci dengan nilai boolean untuk memeriksa apakah item duplikat telah dihasilkan.
Untuk daftar dengan semua elemen yang merupakan tipe hashable:
def gen_dupes(array):
unique = {}
for value in array:
if value in unique and unique[value]:
unique[value] = False
yield value
else:
unique[value] = True
array = [1, 2, 2, 3, 4, 1, 5, 2, 6, 6]
print(list(gen_dupes(array)))
# => [2, 1, 6]
Untuk daftar yang mungkin berisi daftar:
def gen_dupes(array):
unique = {}
for value in array:
is_list = False
if type(value) is list:
value = tuple(value)
is_list = True
if value in unique and unique[value]:
unique[value] = False
if is_list:
value = list(value)
yield value
else:
unique[value] = True
array = [1, 2, 2, [1, 2], 3, 4, [1, 2], 5, 2, 6, 6]
print(list(gen_dupes(array)))
# => [2, [1, 2], 6]
def removeduplicates(a):
seen = set()
for i in a:
if i not in seen:
seen.add(i)
return seen
print(removeduplicates([1,1,2,2]))
Saat menggunakan toolz :
from toolz import frequencies, valfilter
a = [1,2,2,3,4,5,4]
>>> list(valfilter(lambda count: count > 1, frequencies(a)).keys())
[2,4]
inilah cara saya harus melakukannya karena saya menantang diri saya sendiri untuk tidak menggunakan metode lain:
def dupList(oldlist):
if type(oldlist)==type((2,2)):
oldlist=[x for x in oldlist]
newList=[]
newList=newList+oldlist
oldlist=oldlist
forbidden=[]
checkPoint=0
for i in range(len(oldlist)):
#print 'start i', i
if i in forbidden:
continue
else:
for j in range(len(oldlist)):
#print 'start j', j
if j in forbidden:
continue
else:
#print 'after Else'
if i!=j:
#print 'i,j', i,j
#print oldlist
#print newList
if oldlist[j]==oldlist[i]:
#print 'oldlist[i],oldlist[j]', oldlist[i],oldlist[j]
forbidden.append(j)
#print 'forbidden', forbidden
del newList[j-checkPoint]
#print newList
checkPoint=checkPoint+1
return newList
jadi sampel Anda berfungsi sebagai:
>>>a = [1,2,3,3,3,4,5,6,6,7]
>>>dupList(a)
[1, 2, 3, 4, 5, 6, 7]
duplist = list(set(a))
.