Pustaka NumPy digunakan dalam python untuk membuat satu atau lebih array dimensi, dan memiliki banyak fungsi untuk bekerja dengan array. Fungsi unique() adalah salah satu fungsi library ini yang berguna untuk mengetahui nilai unik array dan mengembalikan nilai unik yang diurutkan. Fungsi ini juga dapat mengembalikan tupel nilai larik, larik indeks asosiatif, dan berapa kali setiap nilai unik muncul di
larik utama. Penggunaan yang berbeda dari fungsi ini ditunjukkan dalam tutorial ini.
Sintaksis:
Sintaks fungsi ini diberikan di bawah ini.
Saya ingin mendapatkan nilai unik dari daftar berikut:
[u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
Output yang saya butuhkan adalah:
[u'nowplaying', u'PBS', u'job', u'debate', u'thenandnow']
Kode ini berfungsi:
output = []
for x in trends:
if x not in output:
output.append(x)
print output
apakah ada solusi yang lebih baik yang harus saya gunakan?
Pertama mendeklarasikan daftar Anda dengan benar, dipisahkan dengan koma. Anda bisa mendapatkan nilai unik dengan mengonversi
daftar ke set.
mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
myset = set(mylist)
print(myset)
Jika Anda menggunakannya lebih lanjut sebagai daftar, Anda harus mengubahnya kembali ke daftar dengan melakukan:
mynewlist = list(myset)
Kemungkinan lain, mungkin lebih cepat adalah menggunakan set dari awal, bukan daftar. Maka kode Anda harus:
output = set()
for x in trends:
output.add(x)
print(output)
Seperti yang telah ditunjukkan, set tidak mempertahankan urutan aslinya. Jika perlu, Anda harus mencari tentang set
yang diatur .
Agar konsisten dengan tipe yang akan saya gunakan:
mylist = list(set(mylist))
jenis apa variabel output Anda?
Python set adalah apa yang Anda butuhkan. Nyatakan output seperti ini:
output = set([]) # initialize an empty set
dan Anda siap untuk menambahkan elemen dengan output.add(elem)
dan pastikan itu unik.
Peringatan: set JANGAN mempertahankan urutan asli daftar.
Contoh yang Anda berikan tidak sesuai dengan daftar di Python. Itu menyerupai dict bersarang, yang mungkin bukan apa yang Anda maksudkan.
Daftar Python:
a = ['a', 'b', 'c', 'd', 'b']
Untuk mendapatkan item unik, cukup ubah menjadi set (yang dapat Anda ubah kembali menjadi daftar jika diperlukan):
b = set(a)
print b
>>> set(['a', 'b', 'c', 'd'])
Jika kita perlu menjaga agar elemen tetap teratur, bagaimana dengan ini:
used = set()
mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = [x for x in mylist if x not in used and (used.add(x) or True)]
Dan satu lagi solusi menggunakan reduce
dan tanpa used
var
sementara.
mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = reduce(lambda l, x: l.append(x) or l if x not in l else l, mylist, [])
PEMBARUAN - Maret, 2019
Dan solusi ke-3, yang merupakan solusi yang rapi, tetapi agak lambat karena .index
adalah O (n).
mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = [x for i, x in enumerate(mylist) if i == mylist.index(x)]
UPDATE - Okt, 2016
Solusi lain dengan reduce
, tetapi kali ini tanpa .append
yang membuatnya lebih mudah dibaca manusia dan lebih mudah dipahami.
mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
unique = reduce(lambda l, x: l+[x] if x not in l else l, mylist, [])
#which can also be writed as:
unique = reduce(lambda l, x: l if x in l else l+[x], mylist, [])
CATATAN: Perlu diketahui bahwa semakin banyak yang bisa dibaca manusia, skripnya lebih buruk.
import timeit
setup = "mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']"
#10x to Michael for pointing out that we can get faster with set()
timeit.timeit('[x for x in mylist if x not in used and (used.add(x) or True)]', setup='used = set();'+setup)
0.4188511371612549
timeit.timeit('[x for x in mylist if x not in used and (used.append(x) or True)]', setup='used = [];'+setup)
0.6157128810882568
timeit.timeit('reduce(lambda l, x: l.append(x) or l if x not in l else l, mylist, [])', setup=setup)
1.8778090476989746
timeit.timeit('reduce(lambda l, x: l+[x] if x not in l else l, mylist, [])', setup=setup)
2.13108491897583
timeit.timeit('reduce(lambda l, x: l if x in l else l+[x], mylist, [])', setup=setup)
2.207760810852051
timeit.timeit('[x for i, x in enumerate(mylist) if i == mylist.index(x)]', setup=setup)
2.3621110916137695
KOMENTAR
JAWABAN
Karena @monica menanyakan pertanyaan yang bagus tentang "bagaimana cara kerjanya?". Untuk semua orang yang memiliki masalah mencari tahu. Saya akan mencoba memberikan penjelasan yang lebih mendalam tentang bagaimana ini bekerja dan sihir apa yang terjadi di sini;)
Jadi dia pertama kali bertanya:
Saya mencoba memahami mengapa unique = [used.append(x) for x in mylist if x not in used]
tidak berfungsi.
Sebenarnya ini berfungsi
>>> used = []
>>> mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
>>> unique = [used.append(x) for x in mylist if x not in used]
>>> print used
[u'nowplaying', u'PBS', u'job', u'debate', u'thenandnow']
>>> print unique
[None, None, None, None, None]
Masalahnya adalah kita
tidak mendapatkan hasil yang diinginkan di dalam variabel unique
, tetapi hanya di dalam variabel used
. Ini karena selama pemahaman daftar .append
memodifikasi variabel used
dan mengembalikan None
.
Jadi untuk mendapatkan hasil ke variabel unique
, dan masih menggunakan logika yang sama dengan .append(x) if x not in used
, kita perlu memindahkan panggilan .append
ini di sisi kanan daftar pemahaman dan hanya mengembalikan x
di sisi kiri.
Tetapi jika kita terlalu naif dan hanya pergi
dengan:
>>> unique = [x for x in mylist if x not in used and used.append(x)]
>>> print unique
[]
Kami tidak akan mendapatkan imbalan apa pun.
Sekali lagi, ini karena metode .append
mengembalikan None
, dan ini memberikan pada ekspresi logis kita tampilan berikut:
x not in used and None
Ini pada dasarnya akan selalu:
- mengevaluasi ke
False
ketika x
berada di used
, - mengevaluasi ke
None
ketika x
tidak dalam used
.
Dan dalam kedua kasus (False
/None
), ini akan diperlakukan sebagai nilai falsy
dan kami akan
mendapatkan daftar kosong sebagai hasilnya.
Tetapi mengapa ini mengevaluasi ke None
ketika x
tidak dalam used
? Seseorang mungkin bertanya.
Yah itu karena ini adalah cara Python hubungan pendek operator
bekerja .
Ekspresi x and y
pertama mengevaluasi x; jika x salah, nilainya dikembalikan; jika tidak, y dievaluasi dan nilai yang dihasilkan dikembalikan.
Jadi ketika x
tidak digunakan (yaitu ketika True
)} _ bagian selanjutnya atau ekspresi akan dievaluasi (used.append(x)
) dan nilainya
(None
) akan dikembalikan.
Tapi itulah yang kami inginkan untuk mendapatkan elemen unik dari daftar dengan duplikat, kami ingin .append
mereka menjadi daftar baru hanya ketika kami menemukan waktu pertama.
Jadi kita benar-benar ingin mengevaluasi used.append(x)
hanya ketika x
tidak dalam used
, mungkin jika ada cara untuk mengubah nilai None
ini menjadi truthy
yang kita akan baik-baik saja, kan?
Ya, ya dan di sinilah jenis kedua operator short-circuit
datang untuk bermain.
Ekspresi x or y
pertama mengevaluasi x; jika x benar, nilainya dikembalikan; jika tidak, y dievaluasi dan nilai yang dihasilkan dikembalikan.
Kita tahu bahwa .append(x)
akan selalu menjadi falsy
, jadi jika kita hanya menambahkan satu or
di sebelahnya, kita akan selalu mendapatkan bagian selanjutnya. Itu sebabnya kami menulis:
x not in used and (used.append(x) or True)
jadi kita dapat mengevaluasi used.append(x)
dan mendapatkan True
sebagai
hasilnya, hanya ketika bagian pertama dari ekspresi (x not in used)
adalah True
.
Cara serupa dapat dilihat pada pendekatan ke-2 dengan metode reduce
.
(l.append(x) or l) if x not in l else l
#similar as the above, but maybe more readable
#we return l unchanged when x is in l
#we append x to l and return l when x is not in l
l if x in l else (l.append(x) or l)
dimana kita:
- Tambahkan
x
ke l
dan kembalikan l
saat x
tidak ada dalam l
. Berkat pernyataan or
.append
dievaluasi dan l
dikembalikan setelah itu. - Kembalikan
l
tidak tersentuh ketika x
ada di l
Mempertahankan pesanan:
# oneliners
# slow -> . --- 14.417 seconds ---
[x for i, x in enumerate(array) if x not in array[0:i]]
# fast -> . --- 0.0378 seconds ---
[x for i, x in enumerate(array) if array.index(x) == i]
# multiple lines
# fastest -> --- 0.012 seconds ---
uniq = []
[uniq.append(x) for x in array if x not in uniq]
uniq
Urutan tidak masalah:
# fastest-est -> --- 0.0035 seconds ---
list(set(array))
Ini adalah solusi sederhana-
list=[u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
list=set(list)
Mendapatkan elemen unik dari Daftar
mylist = [1,2,3,4,5,6,6,7,7,8,8,9,9,10]
Menggunakan Logika Sederhana dari Perangkat - Perangkat adalah daftar item yang unik
mylist=list(set(mylist))
In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Menggunakan Logika
Sederhana
newList=[]
for i in mylist:
if i not in newList:
newList.append(i)
In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Menggunakan metode pop -> pop menghapus item terakhir atau yang diindeks dan menampilkannya kepada pengguna. video
k=0
while k < len(mylist):
if mylist[k] in mylist[k+1:]:
mylist.pop(mylist[k])
else:
k=k+1
In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Menggunakan Numpy
import numpy as np
np.unique(mylist)
In [0]: mylist
Out[0]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Referensi
set - koleksi elemen unik tanpa urutan. Daftar elemen dapat diteruskan ke konstruktor set. Jadi, lewati daftar dengan elemen duplikat, kita ditetapkan dengan elemen unik dan mengubahnya kembali ke daftar lalu dapatkan daftar dengan elemen unik. Saya tidak bisa mengatakan apa-apa tentang kinerja dan memori overhead, tapi saya harap,
itu tidak begitu penting dengan daftar kecil.
list(set(my_not_unique_list))
Sederhana dan singkat.
Jika Anda menggunakan numpy dalam kode Anda (yang mungkin merupakan pilihan yang baik untuk jumlah data yang lebih besar), periksa numpy.unique :
>>> import numpy as np
>>> wordsList = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
>>> np.unique(wordsList)
array([u'PBS', u'debate', u'job', u'nowplaying', u'thenandnow'],
dtype='
( http://docs.scipy.org/doc/numpy/reference/generated/numpy.unique.html )
Seperti
yang Anda lihat, numpy tidak hanya mendukung data numerik, array string juga dimungkinkan. Tentu saja, hasilnya adalah array numpy, tetapi tidak banyak masalah, karena masih berperilaku seperti urutan:
>>> for Word in np.unique(wordsList):
... print Word
...
PBS
debate
job
nowplaying
thenandnow
Jika Anda benar-benar ingin memiliki daftar python Vanilla kembali, Anda selalu dapat memanggil daftar ().
Namun, hasilnya secara otomatis diurutkan, seperti yang Anda lihat dari fragmen kode di atas. Lihat
unik numpy tanpa sortir jika perlu mempertahankan urutan daftar.
Urutan daftar unik yang sama hanya menggunakan kompresi daftar.
> my_list = [1, 2, 1, 3, 2, 4, 3, 5, 4, 3, 2, 3, 1]
> unique_list = [
> e
> for i, e in enumerate(my_list)
> if my_list.index(e) == i
> ]
> unique_list
[1, 2, 3, 4, 5]
enumerates
memberikan indeks i
dan elemen e
sebagai
Tuple
.
my_list.index
mengembalikan indeks pertama dari e
. Jika indeks pertama tidak i
maka iterasi e
saat ini bukan e
pertama dalam daftar.
Edit
Saya harus mencatat bahwa ini bukan cara yang baik untuk melakukannya, dari segi kinerja. Ini adalah hanya cara yang mencapainya hanya menggunakan kompresi daftar.
Dengan menggunakan properti dasar dari Kamus Python:
inp=[u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
d={i for i in inp}
print d
Output akan
menjadi:
set([u'nowplaying', u'job', u'debate', u'PBS', u'thenandnow'])
def get_distinct(original_list):
distinct_list = []
for each in original_list:
if each not in distinct_list:
distinct_list.append(each)
return distinct_list
set
dapat membantu Anda menyaring elemen dari daftar yang merupakan duplikat. Ini akan bekerja dengan baik untuk elemen str
, int
atau Tuple
, tetapi jika daftar Anda mengandung dict
atau elemen list
lainnya, maka Anda akan berakhir dengan pengecualian TypeError
.
Berikut ini adalah solusi pengawetan pesanan umum untuk menangani beberapa (tidak semua) jenis tanpa hash:
def unique_elements(iterable):
seen = set()
result = []
for element in iterable:
hashed = element
if isinstance(element, dict):
hashed = Tuple(sorted(element.iteritems()))
Elif isinstance(element, list):
hashed = Tuple(element)
if hashed not in seen:
result.append(element)
seen.add(hashed)
return result
Hal
pertama, contoh yang Anda berikan bukan daftar yang valid.
example_list = [u'nowplaying',u'PBS', u'PBS', u'nowplaying', u'job', u'debate',u'thenandnow']
Misalkan jika di atas adalah daftar contoh. Kemudian Anda dapat menggunakan resep berikut ini untuk memberikan itertools contoh doc yang dapat mengembalikan nilai unik dan mempertahankan urutan seperti yang Anda butuhkan. Iterable di sini adalah example_list
from itertools import ifilterfalse
def unique_everseen(iterable, key=None):
"List unique elements, preserving order. Remember all elements ever seen."
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
# unique_everseen('ABBCcAD', str.lower) --> A B C D
seen = set()
seen_add = seen.add
if key is None:
for element in ifilterfalse(seen.__contains__, iterable):
seen_add(element)
yield element
else:
for element in iterable:
k = key(element)
if k not in seen:
seen_add(k)
yield element
Sebagai
bonus, Counter
adalah cara sederhana untuk mendapatkan nilai unik dan jumlah untuk setiap nilai:
from collections import Counter
l = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
c = Counter(l)
def setlist(lst=[]):
return list(set(lst))
Untuk mendapatkan nilai unik dari Anda daftar gunakan kode di bawah ini:
trends = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
output = set(trends)
output = list(output)
PENTING: Pendekatan di atas tidak akan berfungsi jika salah satu item dalam daftar
tidak hashable yang merupakan kasus untuk bisa berubah jenis, misalnya daftar atau
dict .
trends = [{'super':u'nowplaying'}, u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
output = set(trends)
Traceback (most recent call last):
File "", line 1, in
TypeError: unhashable type: 'dict'
Itu berarti Anda harus yakin bahwa daftar trends
akan selalu hanya berisi item hashable jika tidak Anda harus menggunakan kode yang lebih canggih:
from copy import deepcopy
try:
trends = [{'super':u'nowplaying'}, [u'PBS',], [u'PBS',], u'nowplaying', u'job', u'debate', u'thenandnow', {'super':u'nowplaying'}]
output = set(trends)
output = list(output)
except TypeError:
trends_copy = deepcopy(trends)
while trends_copy:
trend = trends_copy.pop()
if trends_copy.count(trend) == 0:
output.append(trend)
print output
Berikut ini adalah ringkasan untuk mendapatkan elemen unik yang tidak dipesan atau dipesan.
Diberikan
from collections import OrderedDict
seq = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']
Kode
# Unordered
list(set(seq))
# Out: ['thenandnow', 'PBS', 'debate', 'job', 'nowplaying']
# Order-preserving
list(OrderedDict.fromkeys(seq))
# Out: ['nowplaying', 'PBS', 'job', 'debate', 'thenandnow']
Atau dalam Python 3.6+:
# Order-preserving
list(dict.fromkeys(seq))
# Out: ['nowplaying', 'PBS', 'job', 'debate', 'thenandnow']
Catatan: elemen yang terdaftar harus hashable . Lihat juga detail pada contoh terakhir di posting blog ini.
Selain jawaban sebelumnya, yang
mengatakan bahwa Anda dapat mengonversi daftar untuk ditetapkan, Anda juga dapat melakukannya
mylist = [u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenadnow']
mylist = [i for i in set(mylist)]
output akan menjadi
[u'nowplaying', u'job', u'debate', u'PBS', u'thenadnow']
meskipun pesanan tidak akan dipertahankan.
Jawaban lain yang lebih sederhana adalah (tanpa menggunakan set)
>>> t = [v for i,v in enumerate(mylist) if mylist.index(v) == i]
[u'nowplaying', u'PBS', u'job', u'debate', u'thenadnow']
Saya terkejut bahwa tidak ada yang sejauh ini telah memberikan jawaban langsung:
def unique(sequence):
"""Generate unique items from sequence in the order of first occurrence."""
seen = set()
for value in sequence:
if value in seen:
continue
seen.add(value)
yield value
Ini akan menghasilkan nilai sehingga berfungsi dengan lebih dari sekadar daftar, mis. unique(range(10))
. Untuk mendapatkan daftar, panggil list(unique(sequence))
, seperti ini:
>>> list(unique([u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']))
[u'nowplaying', u'PBS', u'job', u'debate', u'thenandnow']
Ini memiliki persyaratan bahwa setiap item hashable dan bukan hanya sebanding, tetapi sebagian besar barang di Python adalah dan itu O(n) dan bukan O (n ^ 2), sehingga akan bekerja dengan baik dengan panjang daftar.
gunakan set untuk menghapus duplikat daftar, kembali sebagai daftar
def get_unique_list(lst):
if isinstance(lst,list):
return list(set(lst))
- Di awal kode Anda cukup nyatakan daftar output Anda kosong:
output=[]
- Alih-alih kode Anda, Anda dapat menggunakan kode ini
trends=list(set(trends))
Anda bisa menggunakan set. Untuk lebih jelasnya, saya menjelaskan apa perbedaan antara daftar dan satu set. set adalah kumpulan elemen unik yang tidak diurut. Daftar adalah kumpulan elemen yang diurutkan. Begitu,
unicode_list=[u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job',u'debate', u'thenandnow']
list_unique=list(set(unicode_list))
print list_unique
[u'nowplaying', u'job', u'debate', u'PBS', u'thenandnow']
Tetapi: Jangan gunakan daftar/set dalam menamai variabel. Ini akan menyebabkan
kesalahan: EX: Alih-alih menggunakan daftar alih-alih unicode_list di atas.
list=[u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job',u'debate', u'thenandnow']
list_unique=list(set(list))
print list_unique
list_unique=list(set(list))
TypeError: 'list' object is not callable
Set adalah kumpulan elemen teratur dan unik. Jadi, Anda dapat menggunakan set seperti di bawah ini untuk mendapatkan daftar unik:
unique_list = list(set([u'nowplaying', u'PBS', u'PBS', u'nowplaying', u'job', u'debate', u'thenandnow']))
Jika Anda ingin mendapatkan elemen unik dari daftar dan mempertahankan urutan aslinya, maka Anda
dapat menggunakan OrderedDict
struktur data dari pustaka standar Python:
from collections import OrderedDict
def keep_unique(elements):
return list(OrderedDict.fromkeys(elements).keys())
elements = [2, 1, 4, 2, 1, 1, 5, 3, 1, 1]
required_output = [2, 1, 4, 5, 3]
assert keep_unique(elements) == required_output
Bahkan, jika Anda menggunakan Python ≥ 3.6, Anda dapat menggunakan dict
polos untuk itu:
def keep_unique(elements):
return list(dict.fromkeys(elements).keys())
Ini menjadi mungkin setelah pengenalan representasi "kompak" dari dikt. Lihat sini . Padahal ini "dianggap sebagai detail implementasi dan tidak boleh diandalkan".
Solusi saya untuk memeriksa konten untuk keunikan tetapi mempertahankan pesanan asli:
def getUnique(self):
notunique = self.readLines()
unique = []
for line in notunique: # Loop over content
append = True # Will be set to false if line matches existing line
for existing in unique:
if line == existing: # Line exists ? do not append and go to the next line
append = False
break # Already know file is unique, break loop
if append: unique.append(line) # Line not found? add to list
return unique
Sunting: Mungkin bisa lebih efisien dengan menggunakan kunci kamus untuk memeriksa keberadaan daripada melakukan seluruh file loop untuk setiap baris, saya tidak akan menggunakan solusi saya untuk set besar.
Saya tahu ini
adalah pertanyaan lama, tapi inilah solusi unik saya: warisan kelas !:
class UniqueList(list):
def appendunique(self,item):
if item not in self:
self.append(item)
return True
return False
Kemudian, jika Anda ingin menambahkan item secara unik ke daftar, Anda cukup memanggil appendunique di UniqueList. Karena mewarisi dari daftar, pada dasarnya bertindak seperti daftar, sehingga Anda dapat menggunakan fungsi seperti index () dll. Dan karena mengembalikan benar atau salah, Anda dapat mengetahui apakah menambahkan berhasil (item unik) atau gagal (sudah ada di daftar).
Untuk mendapatkan daftar
item yang unik dari daftar, gunakan for for loop menambahkan item ke UniqueList (lalu salin ke daftar).
Contoh kode penggunaan:
unique = UniqueList()
for each in [1,2,2,3,3,4]:
if unique.appendunique(each):
print 'Uniquely appended ' + str(each)
else:
print 'Already contains ' + str(each)
Cetakan:
Uniquely appended 1
Uniquely appended 2
Already contains 2
Uniquely appended 3
Already contains 3
Uniquely appended 4
Menyalin ke daftar:
unique = UniqueList()
for each in [1,2,2,3,3,4]:
unique.appendunique(each)
newlist = unique[:]
print newlist
Cetakan:
[1, 2, 3, 4]