Cara menggunakan NP.UNIQUE pada Python

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:

  1. mengevaluasi ke False ketika x berada di used,
  2. 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:

  1. Tambahkan x ke l dan kembalikan l saat x tidak ada dalam l. Berkat pernyataan or.append dievaluasi dan l dikembalikan setelah itu.
  2. 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))

  1. Di awal kode Anda cukup nyatakan daftar output Anda kosong: output=[]
  2. 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]