Alisin at kunin ang mga duplicate na elemento mula sa isang listahan (array) sa Python

Negosyo

Inilalarawan ng seksyong ito kung paano bumuo ng isang bagong listahan sa Python sa pamamagitan ng pag-alis o pagkuha ng mga duplicate na elemento mula sa isang listahan (array).

Ang mga sumusunod na detalye ay inilarawan dito.

  • Alisin ang mga duplicate na elemento at bumuo ng mga bagong listahan
    • Huwag panatilihin ang pagkakasunud-sunod ng orihinal na listahan:set()
    • Pinapanatili ang pagkakasunud-sunod ng orihinal na listahan:dict.fromkeys(),sorted()
    • Dalawang-dimensional na array (listahan ng mga listahan)
  • I-extract ang mga duplicate na elemento at bumuo ng bagong listahan
    • Huwag panatilihin ang pagkakasunud-sunod ng orihinal na listahan
    • Pinapanatili ang pagkakasunud-sunod ng orihinal na listahan
    • Dalawang-dimensional na array (listahan ng mga listahan)

Ang parehong konsepto ay maaaring ilapat sa mga tuple sa halip na mga listahan.

Tingnan ang sumusunod na artikulo para sa

  • Kung gusto mong matukoy kung ang isang listahan o tuple ay may mga duplicate na elemento
  • Kung gusto mong kunin ang mga elemento na karaniwan o hindi karaniwan sa maraming listahan sa halip na isang listahan

Tandaan na ang mga listahan ay maaaring mag-imbak ng iba’t ibang uri ng data at mahigpit na naiiba sa mga array. Kung gusto mong pangasiwaan ang mga array sa mga prosesong nangangailangan ng laki ng memory at mga address ng memory o numerical processing ng malaking data, gumamit ng array (standard library) o NumPy.

Alisin ang mga duplicate na elemento at bumuo ng mga bagong listahan

Huwag panatilihin ang pagkakasunud-sunod ng orihinal na listahan:set()

Kung hindi kailangang panatilihin ang pagkakasunud-sunod ng orihinal na listahan, gamitin ang set(), na bumubuo ng set ng uri ng hanay.

Ang uri ng hanay ay isang uri ng data na walang mga duplicate na elemento. Kapag ang isang listahan o iba pang uri ng data ay ipinasa sa set(), ang mga duplicate na halaga ay babalewalain at ang isang object ng uri ng set ay ibinalik kung saan ang mga natatanging halaga lamang ang mga elemento.

Kung gusto mong gawin itong tuple, gamitin ang tuple().

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

print(set(l))
# {1, 2, 3, 4, 5}

print(list(set(l)))
# [1, 2, 3, 4, 5]

Siyempre, maaari rin itong iwanang nakatakda. Tingnan ang sumusunod na artikulo para sa higit pang impormasyon sa hanay ng uri ng hanay.

Pinapanatili ang pagkakasunud-sunod ng orihinal na listahan:dict.fromkeys(),sorted()

Kung gusto mong panatilihin ang pagkakasunud-sunod ng orihinal na listahan, gamitin ang class method fromkeys() ng uri ng diksyunaryo o ang built-in na function sorted().

Gumagawa ang dict.fromkeys() ng bagong object ng diksyunaryo na ang mga key ay mga listahan, tuple, atbp. na tinukoy sa mga argumento. Kung ang pangalawang argumento ay tinanggal, ang halaga ay Wala.

Dahil ang mga susi ng diksyunaryo ay walang mga dobleng elemento, ang mga duplicate na halaga ay binabalewala tulad ng sa set(). Bilang karagdagan, ang isang object ng diksyunaryo ay maaaring ipasa bilang isang argumento sa list() upang makakuha ng isang listahan na ang mga elemento ay mga key ng diksyunaryo.

print(dict.fromkeys(l))
# {3: None, 2: None, 1: None, 5: None, 4: None}

print(list(dict.fromkeys(l)))
# [3, 2, 1, 5, 4]

Ito ay ginagarantiyahan mula noong Python 3.7 (CPython ay 3.6) na pinapanatili ng dict.fromkeys() ang pagkakasunud-sunod ng pagkakasunud-sunod ng argumento. Ginagamit ng mga naunang bersyon ang built-in na function sorted() bilang mga sumusunod.

Tukuyin ang list tuple method index() para sa argument key ng sorted, na nagbabalik ng pinagsunod-sunod na listahan ng mga elemento.

index() ay isang paraan na nagbabalik ng index ng halaga (ang bilang ng elemento sa listahan), na maaaring tukuyin bilang susi ng sorted() upang pagbukud-bukurin ang listahan batay sa pagkakasunud-sunod ng orihinal na listahan. Ang argument key ay tinukoy bilang isang bagay na matatawag (matatawag), kaya huwag isulat ang ().

print(sorted(set(l), key=l.index))
# [3, 2, 1, 5, 4]

Dalawang-dimensional na array (listahan ng mga listahan)

Para sa mga two-dimensional na array (listahan ng mga listahan), ang paraan gamit ang set() o dict.fromkeys() ay nagreresulta sa isang TypeError.

l_2d = [[1, 1], [0, 1], [0, 1], [0, 0], [1, 0], [1, 1], [1, 1]]

# l_2d_unique = list(set(l_2d))
# TypeError: unhashable type: 'list'

# l_2d_unique_order = dict.fromkeys(l_2d)
# TypeError: unhashable type: 'list'

Ito ay dahil ang mga non-hashable na bagay gaya ng mga listahan ay hindi maaaring mga elemento ng type set o mga key ng type na dict.

Tukuyin ang mga sumusunod na function Ang pagkakasunud-sunod ng orihinal na listahan ay pinapanatili at gumagana para sa mga one-dimensional na listahan at tuple.

def get_unique_list(seq):
    seen = []
    return [x for x in seq if x not in seen and not seen.append(x)]

print(get_unique_list(l_2d))
# [[1, 1], [0, 1], [0, 0], [1, 0]]

print(get_unique_list(l))
# [3, 2, 1, 5, 4]

Ginagamit ang notasyon sa pag-unawa sa listahan.

Dito, ginagamit namin ang sumusunod

  • Kung ang X sa “X at Y” ay mali sa short-circuit na pagsusuri ng at operator, kung gayon ang Y ay hindi sinusuri (hindi naisakatuparan).
  • Ang paraan ng append() ay nagbabalik ng Wala.

Kung ang mga elemento ng orihinal na listahan seq ay hindi umiiral sa nakita, pagkatapos at pagkatapos ay sinusuri.
seen.append(x) ay pinaandar at ang elemento ay idinaragdag sa seen.
Dahil ang append() method ay nagbabalik ng None at None is False, not seen.append(x) ay nagsusuri sa True.
Nagiging True ang conditional expression sa notation ng pang-unawa sa listahan at idinaragdag bilang elemento ng panghuling nabuong listahan.

Kung ang mga elemento ng orihinal na list seq ay nasa seen, ang x not in seen ay False, at ang conditional expression para sa list comprehension expression ay False.
Samakatuwid, hindi sila idinagdag bilang mga elemento ng panghuling nabuong listahan.

Ang isa pang paraan ay ang itakda ang argument axis sa function ng NumPy np.unique(), bagama’t ang resulta ay pag-uuri-uriin.

I-extract ang mga duplicate na elemento at bumuo ng bagong listahan

Huwag panatilihin ang pagkakasunud-sunod ng orihinal na listahan

Upang kunin lamang ang mga duplicate na elemento mula sa orihinal na listahan, gamitin ang collections.Counter().
Nagbabalik ng collections.Counter (isang subclass ng diksyunaryo) na may mga elemento bilang mga susi at ang bilang ng mga elemento bilang mga halaga.

import collections

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

print(collections.Counter(l))
# Counter({3: 3, 2: 2, 1: 2, 5: 1, 4: 1})

Dahil ito ay isang subclass ng diksyunaryo, ang mga item() ay maaaring gamitin upang kunin ang mga key at value. Ito ay sapat na upang kunin ang mga susi na ang bilang ay dalawa o higit pa.

print([k for k, v in collections.Counter(l).items() if v > 1])
# [3, 2, 1]

Pinapanatili ang pagkakasunud-sunod ng orihinal na listahan

Tulad ng ipinapakita sa halimbawa sa itaas, mula noong Python 3.7, ang mga susi ng mga koleksyon. Pinapanatili ng Counter ang pagkakasunud-sunod ng orihinal na listahan at iba pa.

Sa mga naunang bersyon, ang pag-uuri gamit ang sorted() ay sapat na, tulad ng pagtanggal ng mga duplicate na elemento.

print(sorted([k for k, v in collections.Counter(l).items() if v > 1], key=l.index))
# [3, 2, 1]

Kung gusto mong kunin ang mga duplicate kung ano ang mga ito, iwanan lang ang mga elemento mula sa orihinal na listahan na may bilang na dalawa o higit pa. Ang pagkakasunud-sunod ay napanatili din.

cc = collections.Counter(l)
print([x for x in l if cc[x] > 1])
# [3, 3, 2, 1, 1, 2, 3]

Dalawang-dimensional na array (listahan ng mga listahan)

Para sa mga two-dimensional na array (listahan ng mga listahan), ang mga sumusunod na function ay posible kapag ang pagkakasunud-sunod ng orihinal na listahan ay hindi pinanatili at kapag ito ay pinanatili, ayon sa pagkakabanggit. Gumagana rin ito para sa mga one-dimensional na listahan at tuple.

l_2d = [[1, 1], [0, 1], [0, 1], [0, 0], [1, 0], [1, 1], [1, 1]]
def get_duplicate_list(seq):
    seen = []
    return [x for x in seq if not seen.append(x) and seen.count(x) == 2]

def get_duplicate_list_order(seq):
    seen = []
    return [x for x in seq if seq.count(x) > 1 and not seen.append(x) and seen.count(x) == 1]

print(get_duplicate_list(l_2d))
# [[0, 1], [1, 1]]

print(get_duplicate_list_order(l_2d))
# [[1, 1], [0, 1]]

print(get_duplicate_list(l))
# [3, 1, 2]

print(get_duplicate_list_order(l))
# [3, 2, 1]

Kung gusto mong mag-extract gamit ang mga duplicate, mag-iwan ng mga elemento mula sa orihinal na listahan na may bilang na dalawa o higit pa.

print([x for x in l_2d if l_2d.count(x) > 1])
# [[1, 1], [0, 1], [0, 1], [1, 1], [1, 1]]

Tandaan na dahil ang computational complexity ng count() ay O(n), ang function na ipinapakita sa itaas na paulit-ulit na nagpapatupad ng count() ay napaka-inefficient. Maaaring may mas matalinong paraan.

Ang Counter ay isang subclass ng diksyunaryo, kaya kung magpapasa ka ng isang listahan o tuple na ang mga elemento ay mga listahan o iba pang hindi na-hashable na mga bagay sa mga koleksyon. Counter(), may magaganap na error at hindi mo ito magagamit.

# print(collections.Counter(l_2d))
# TypeError: unhashable type: 'list'