Αφαίρεση και εξαγωγή διπλών στοιχείων από μια λίστα (πίνακα) στην Python

Επιχείρηση

Αυτή η ενότητα περιγράφει πώς να δημιουργήσετε μια νέα λίστα στην Python αφαιρώντας ή αφαιρώντας διπλά στοιχεία από μια λίστα (πίνακα).

Εδώ περιγράφονται οι ακόλουθες λεπτομέρειες.

  • Αφαιρέστε διπλά στοιχεία και δημιουργήστε νέες λίστες
    • Μην διατηρείτε τη σειρά της αρχικής καταχώρισης:set()
    • Διατηρεί τη σειρά της αρχικής καταχώρισης: dict.fromkeys(),sorted()
    • Δισδιάστατος πίνακας (λίστα λιστών)
  • Εξαγωγή διπλών στοιχείων και δημιουργία νέας λίστας
    • Μην διατηρείτε τη σειρά της αρχικής καταχώρισης
    • Διατηρεί τη σειρά της αρχικής καταχώρισης
    • Δισδιάστατος πίνακας (λίστα λιστών)

Η ίδια έννοια μπορεί να εφαρμοστεί σε πλειάδες αντί για λίστες.

Δείτε το ακόλουθο άρθρο για

  • Αν θέλετε να προσδιορίσετε αν μια λίστα ή πλειάδα έχει διπλά στοιχεία
  • Εάν θέλετε να εξάγετε στοιχεία που είναι κοινά ή όχι κοινά μεταξύ πολλαπλών καταχωρίσεων αντί για μία μόνο καταχώριση

Σημειώστε ότι οι λίστες μπορούν να αποθηκεύουν διαφορετικούς τύπους δεδομένων και διαφέρουν αυστηρά από τους πίνακες. Αν θέλετε να χειρίζεστε πίνακες σε διαδικασίες που απαιτούν μέγεθος μνήμης και διευθύνσεις μνήμης ή αριθμητική επεξεργασία μεγάλων δεδομένων, χρησιμοποιήστε array (standard library) ή NumPy.

Αφαιρέστε διπλά στοιχεία και δημιουργήστε νέες λίστες

Μην διατηρείτε τη σειρά της αρχικής καταχώρισης: set()

Αν δεν χρειάζεται να διατηρηθεί η σειρά της αρχικής λίστας, χρησιμοποιήστε τη set(), η οποία παράγει ένα σύνολο τύπου set.

Ο τύπος συνόλου είναι ένας τύπος δεδομένων που δεν έχει διπλά στοιχεία. Όταν μια λίστα ή άλλος τύπος δεδομένων περνάει στη set(), οι διπλές τιμές αγνοούνται και επιστρέφεται ένα αντικείμενο τύπου set στο οποίο μόνο οι μοναδικές τιμές είναι στοιχεία.

Αν θέλετε να το κάνετε πλειάδα, χρησιμοποιήστε την 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]

Φυσικά, μπορεί επίσης να παραμείνει ως έχει. Δείτε το ακόλουθο άρθρο για περισσότερες πληροφορίες σχετικά με τον τύπο set set.

Διατηρεί τη σειρά της αρχικής καταχώρισης: dict.fromkeys(),sorted()

Αν θέλετε να διατηρήσετε τη σειρά της αρχικής λίστας, χρησιμοποιήστε τη μέθοδο κλάσης fromkeys() του τύπου λεξικού ή την ενσωματωμένη συνάρτηση sorted().

Η dict.fromkeys() δημιουργεί ένα νέο αντικείμενο λεξικού του οποίου τα κλειδιά είναι λίστες, πλειάδες κ.λπ. που καθορίζονται στα ορίσματα. Εάν το δεύτερο όρισμα παραλείπεται, η τιμή είναι None.

Δεδομένου ότι τα κλειδιά του λεξικού δεν έχουν διπλά στοιχεία, οι διπλές τιμές αγνοούνται όπως και στη set(). Επιπλέον, ένα αντικείμενο λεξικού μπορεί να περάσει ως όρισμα στην list() για να ληφθεί μια λίστα της οποίας τα στοιχεία είναι κλειδιά λεξικού.

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

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

Από την Python 3.7 (η CPython είναι 3.6) έχει εξασφαλιστεί ότι η dict.fromkeys() διατηρεί τη σειρά της ακολουθίας των επιχειρημάτων. Παλαιότερες εκδόσεις χρησιμοποιούν την ενσωματωμένη συνάρτηση sorted() ως εξής.

Καθορίστε τη μέθοδο πλειάδας λίστας index() για το όρισμα key της sorted, η οποία επιστρέφει μια ταξινομημένη λίστα στοιχείων.

Η index() είναι μια μέθοδος που επιστρέφει το δείκτη της τιμής (τον αριθμό του στοιχείου στη λίστα), ο οποίος μπορεί να καθοριστεί ως κλειδί της sorted() για να ταξινομηθεί η λίστα με βάση τη σειρά της αρχικής λίστας. Το όρισμα key καθορίζεται ως αντικείμενο που μπορεί να κληθεί (callable), οπότε μην γράφετε ().

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

Δισδιάστατος πίνακας (λίστα λιστών)

Για δισδιάστατους πίνακες (λίστες λιστών), η μέθοδος που χρησιμοποιεί set() ή dict.fromkeys() οδηγεί σε 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'

Αυτό οφείλεται στο γεγονός ότι τα αντικείμενα που δεν μπορούν να διακινδυνεύονται, όπως οι λίστες, δεν μπορούν να είναι στοιχεία τύπου set ή κλειδιά τύπου dict.

Ορίστε τις ακόλουθες συναρτήσεις Η σειρά της αρχικής λίστας διατηρείται και λειτουργεί για μονοδιάστατες λίστες και πλειάδες.

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]

Χρησιμοποιείται συμβολισμός κατανόησης λίστας.

Εδώ, χρησιμοποιούμε τα ακόλουθα

  • Εάν το X στο «X και Y» είναι ψευδές στην αξιολόγηση βραχυκυκλώματος του τελεστή and, τότε το Y δεν αξιολογείται (δεν εκτελείται).
  • Η μέθοδος append() επιστρέφει None.

Εάν τα στοιχεία της αρχικής λίστας seq δεν υπάρχουν στην seen, τότε αξιολογούνται οι και after.
Η seen.append(x) εκτελείται και το στοιχείο προστίθεται στην seen.
Επειδή η μέθοδος append() επιστρέφει None και το None είναι False, το not seen.append(x) αξιολογείται ως True.
Η υπό συνθήκη έκφραση στον συμβολισμό κατανόησης λίστας γίνεται Αληθής και προστίθεται ως στοιχείο της τελικής παραγόμενης λίστας.

Εάν τα στοιχεία της αρχικής λίστας seq υπάρχουν στην seen, τότε το x που δεν υπάρχει στην seen είναι False και η υπό συνθήκη έκφραση για την έκφραση κατανόησης της λίστας είναι False.
Ως εκ τούτου, δεν προστίθενται ως στοιχεία του τελικού παραγόμενου καταλόγου.

Μια άλλη μέθοδος είναι να ορίσετε τον άξονα των επιχειρημάτων στη συνάρτηση np.unique() της NumPy, αν και το αποτέλεσμα θα είναι ταξινομημένο.

Εξαγωγή διπλών στοιχείων και δημιουργία νέας λίστας

Μην διατηρείτε τη σειρά της αρχικής καταχώρισης

Για να εξαγάγετε μόνο τα διπλά στοιχεία από την αρχική λίστα, χρησιμοποιήστε την collections.Counter().
Επιστρέφει ένα collections.Counter (υποκατηγορία του λεξικού) με τα στοιχεία ως κλειδιά και τον αριθμό των στοιχείων ως τιμές.

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})

Δεδομένου ότι είναι υποκλάση του λεξικού, η items() μπορεί να χρησιμοποιηθεί για την ανάκτηση κλειδιών και τιμών. Αρκεί να εξάγετε κλειδιά των οποίων ο αριθμός είναι δύο ή περισσότεροι.

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

Διατηρεί τη σειρά της αρχικής καταχώρισης

Όπως φαίνεται στο παραπάνω παράδειγμα, από την Python 3.7, τα κλειδιά της collections.Counter διατηρούν τη σειρά της αρχικής λίστας και ούτω καθεξής.

Σε προηγούμενες εκδόσεις, η ταξινόμηση με την sorted() είναι επαρκής, όπως και η διαγραφή διπλών στοιχείων.

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

Αν θέλετε να εξάγετε τα αντίγραφα ως έχουν, απλά αφήστε τα στοιχεία της αρχικής λίστας με αριθμό δύο ή περισσότερο. Η σειρά διατηρείται επίσης.

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

Δισδιάστατος πίνακας (λίστα λιστών)

Για δισδιάστατους πίνακες (λίστες λιστών), οι ακόλουθες συναρτήσεις είναι δυνατές όταν η σειρά της αρχικής λίστας δεν διατηρείται και όταν διατηρείται, αντίστοιχα. Λειτουργεί επίσης για μονοδιάστατες λίστες και πλειάδες.

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]

Αν θέλετε να εξάγετε με αντίγραφα, αφήστε στοιχεία από την αρχική λίστα με αριθμό δύο ή περισσότερα.

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

Σημειώστε ότι δεδομένου ότι η υπολογιστική πολυπλοκότητα της count() είναι O(n), η συνάρτηση που παρουσιάζεται παραπάνω και εκτελεί επανειλημμένα την count() είναι πολύ αναποτελεσματική. Μπορεί να υπάρχει ένας πιο έξυπνος τρόπος.

Ο μετρητής είναι μια υποκλάση του λεξικού, οπότε αν περάσετε μια λίστα ή πλειάδα της οποίας τα στοιχεία είναι λίστες ή άλλα μη-καταχωρίσιμα αντικείμενα στη collections.Counter(), θα εμφανιστεί σφάλμα και δεν θα μπορείτε να τη χρησιμοποιήσετε.

# print(collections.Counter(l_2d))
# TypeError: unhashable type: 'list'
Copied title and URL