Cách dễ dàng loại bỏ các bản sao khỏi Python List
03/11/2022 01:30
list Python là một tập hợp các đối tượng có thứ tự, không được lập chỉ mục và có thể thay đổi. Chúng ta tạo nó bằng cách đặt các đối tượng có kiểu dữ liệu tương tự hoặc khác nhau bên trong dấu ngoặc vuông được phân tách bằng dấu phẩy. Để biết thêm về cách hoạt động của list Python, vui lòng tham khảo hướng dẫn này .
list Python là một tập hợp các đối tượng có thứ tự, không được lập chỉ mục và có thể thay đổi. Chúng ta tạo nó bằng cách đặt các đối tượng có kiểu dữ liệu tương tự hoặc khác nhau bên trong dấu ngoặc vuông được phân tách bằng dấu phẩy. Để biết thêm về cách hoạt động của list Python, vui lòng tham khảo hướng dẫn này .
Xóa các mục trùng lặp khỏi list là một bước xử lý trước dữ liệu quan trọng - ví dụ: xác định những khách hàng duy nhất đã mua hàng từ cửa hàng quà tặng trong tháng qua để nhận ưu đãi khuyến mại. Một số khách hàng có thể đã mua quà tặng từ cửa hàng nhiều hơn một lần trong tháng qua và tên của họ sẽ xuất hiện nhiều lần khi họ ghé thăm cửa hàng.
Trong hướng dẫn này, chúng ta sẽ tìm hiểu các phương pháp khác nhau để xóa các bản sao khỏi list Python.
1. Sử dụng del
từ khóa
Chúng ta sử dụng del
từ khóa để xóa các đối tượng khỏi list với vị trí chỉ mục của chúng. Chúng ta sử dụng phương pháp này khi kích thước của list nhỏ và không có nhiều phần tử trùng lặp. Ví dụ, một lớp sáu sinh viên được hỏi về ngôn ngữ lập trình yêu thích của họ và câu trả lời của họ được lưu trong students
list. Một số sinh viên thích cùng một ngôn ngữ lập trình, vì vậy chúng ta có các bản sao trong students
list mà chúng ta sẽ xóa bằng cách sử dụng del
từ khóa.
students = ['Python', 'R', 'C#', 'Python', 'R', 'Java']
# Remove the `Python` duplicate with its index number: 3
del students[3]
print(students)
['Python', 'R', 'C#', 'R', 'Java']
# Remove the `R` duplicate with its index number: 3
del students[3]
print(students)
['Python', 'R', 'C#', 'Java']
Chúng ta đã xóa thành công các bản sao khỏi list. Nhưng tại sao chúng ta lại sử dụng chỉ mục 3 hai lần? list len
ban đầu students
là 6. list Python không được lập chỉ mục. Phần tử đầu tiên trong list có chỉ số là 0 và phần tử cuối cùng có chỉ số là 5. Phần tử trùng lặp 'Python'
có chỉ số là 3. Sau khi xóa phần tử 'Python'
trùng lặp, phần len
tử của students
list giảm đi 1. Phần tử sau bản sao 'Python'
bây giờ giả định vị trí chỉ mục của nó. Đây là lý do tại sao 'R'
chỉ mục trùng lặp thay đổi từ 4 thành 3. Nhược điểm của việc sử dụng phương pháp này là chúng ta phải theo dõi các chỉ số của các bản sao luôn thay đổi. Điều này sẽ khó đối với một list rất lớn.
Tiếp theo, chúng ta sẽ xóa các bản sao khỏi list bằng cách sử dụng hiệu quả hơn for-loop
.
2. Sử dụngfor-loop
Chúng ta sử dụng for-loop
để lặp qua một list có thể lặp lại: ví dụ, một list Python. Để có người tham khảo về cách for-loop
hoạt động, vui lòng tham khảo hướng dẫn vòng lặp này trên blog DataQuest.
Để loại bỏ các bản sao bằng cách sử dụng for-loop
, trước tiên, bạn tạo một list trống mới. Sau đó, bạn lặp lại các phần tử trong list có chứa các bản sao và chỉ thêm lần xuất hiện đầu tiên của mỗi phần tử trong list mới. Đoạn mã dưới đây cho thấy cách sử dụng for-loop
để xóa các bản sao khỏi students
list.
# Using for-loop
students = ['Python', 'R', 'C#', 'Python', 'R', 'Java']
new_list = []
for one_student_choice in students:
if one_student_choice not in new_list:
new_list.append(one_student_choice)
print(new_list)
['Python', 'R', 'C#', 'Java']
Voilà! Chúng ta đã xóa thành công các bản sao mà không cần phải theo dõi các chỉ số của phần tử. Phương pháp này có thể giúp chúng ta loại bỏ các bản sao trong một list lớn. Tuy nhiên, điều này đòi hỏi rất nhiều mã. Nên có một cách đơn giản hơn để làm điều này. Đoán nào?
Liệt kê dễ hiểu! Chúng ta sẽ đơn giản hóa đoạn mã trên bằng cách sử dụng tính năng hiểu list trong ví dụ tiếp theo:
# Using list comprehension
new_list = []
[new_list.append(item) for item in students if item not in new_list]
print(new_list)
['Python', 'R', 'C#', 'Java']
Chúng ta đã hoàn thành công việc với ít dòng mã hơn. Chúng ta có thể kết hợp for-loop
với các hàm enumerate
và zip
để viết các đoạn mã lạ nhằm loại bỏ các đoạn mã trùng lặp. Ý tưởng đằng sau cách các mã này hoạt động giống như trong các ví dụ được hiển thị ở trên.
Tiếp theo, chúng ta sẽ xem cách xóa các bản sao khỏi list mà không cần lặp lại bằng cách sử dụng a set
.
3. Sử dụngset
Tập hợp trong Python là các tập hợp không có thứ tự của các phần tử duy nhất. Theo bản chất của chúng, các bản sao không được phép. Do đó, việc chuyển đổi một list thành một tập hợp sẽ loại bỏ các bản sao. Thay đổi tập hợp thành một list sẽ tạo ra một list mới không có bản sao.
Ví dụ sau đây cho thấy cách loại bỏ các bản sao khỏi students
list bằng cách sử dụng set
.
# Removing duplicates by first changing to a set and then back to a list
new_list = list(set(students))
print(new_list)
['R', 'Python', 'Java', 'C#']
Lưu ý rằng thứ tự của các phần tử trong list khác với các ví dụ trước của chúng ta. Điều này là do một set
đơn đặt hàng không bảo toàn. Tiếp theo, chúng ta sẽ xem cách xóa các từ trùng lặp khỏi list bằng cách sử dụng từ điển.
4. Sử dụngdict
Từ điển Python là một tập hợp các cặp khóa-giá trị với yêu cầu là các khóa phải là duy nhất. Vì vậy, chúng ta sẽ xóa các bản sao trong list Python nếu chúng ta có thể làm cho các phần tử của list trở thành khóa của từ điển. Chúng ta không thể chuyển đổi students
list đơn giản thành từ điển vì từ điển được tạo bằng cặp khóa-giá trị. Chúng ta gặp lỗi sau nếu chúng ta cố gắng chuyển đổi students
list sang từ điển:
# We get ValueError when we try to convert a simple list into a dictionary
print(dict(students))
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-6-43bfe4b3db83> in <module>
1 # We get ValueError when we try to convert a simple list into a dictionary
2
----> 3 dict(students)
ValueError: dictionary update sequence element #0 has length 6; 2 is required
Tuy nhiên, chúng ta có thể tạo một từ điển từ một list các bộ giá trị - sau đó chúng ta sẽ lấy các khóa duy nhất của từ điển và chuyển chúng thành một list. Một cách được vector hóa để lấy list các bộ giá trị từ students
list là sử dụng chức năng bản đồ:
# Convert `students` list into a list of tuples
list_of_tuples = list(map(lambda x: (x, None), students))
print(list_of_tuples, end='\n\n')
[('Python', None), ('R', None), ('C#', None), ('Python', None), ('R', None), ('Java', None)]
Trong khối mã trên, mọi phần tử trong students
list được chuyển qua lambda
hàm để tạo một bộ giá trị (element, None)
,. Khi list các bộ giá trị được thay đổi thành một từ điển, phần tử đầu tiên trong bộ giá trị là khóa và phần tử thứ hai là giá trị. Các khóa duy nhất là từ từ điển với keys()
phương thức và được thay đổi thành một list:
# Convert list of tuples into a dictionary
dict_students = dict(list_of_tuples)
print('The resulting dictionary from the list of tuples:')
print(dict_students, end='\n\n')
The resulting dictionary from the list of tuples:
{'Python': None, 'R': None, 'C#': None, 'Java': None}
# Get the unique keys from the dictionary and convert into a list
new_list = list(dict_students.keys())
print('The new list without duplicates:')
print(new_list, end='\n\n')
The new list without duplicates:
['Python', 'R', 'C#', 'Java']
Phương dict.fromkeys()
pháp chuyển đổi một list thành một list các bộ giá trị và list các bộ giá trị thành một từ điển trong một lần thực hiện. Sau đó, chúng ta có thể lấy các khóa từ điển duy nhất và chuyển đổi chúng thành một list. Tuy nhiên, chúng ta đã sử dụng dict.keys()
phương pháp này để lấy các khóa duy nhất từ từ điển trước khi chuyển đổi thành list. Điều này không thực sự cần thiết. Theo mặc định, các thao tác trên từ điển như lặp và chuyển đổi thành list sử dụng các khóa từ điển.
# Using dict.fromkeys() methods to get a dictionary from a list
new_dict_students = dict.fromkeys(students)
print('The resulting dictionary from the dict.fromkeys():')
print(new_dict_students, end='\n\n')
print('The new list without duplicates using dict.fromkeys():')
print(list(new_dict_students), end='\n\n')
The resulting dictionary from the dict.fromkeys():
{'Python': None, 'R': None, 'C#': None, 'Java': None}
The new list without duplicates using dict.fromkeys():
['Python', 'R', 'C#', 'Java']
4. Sử dụng Counter
vàFreqDist
Chúng ta có thể xóa các bản sao khỏi list Python bằng cách sử dụng các lớp con từ điển như Counter
và FreqDist
. Cả hai Counter
và FreqDist
hoạt động theo cùng một cách. Chúng là các tập hợp trong đó các phần tử duy nhất là các khóa từ điển và số lần xuất hiện của chúng là các giá trị. Như trong từ điển, list không có bản sao đến từ các khóa từ điển.
# Using the dict subclass FreqDist
from nltk.probability import FreqDist
freq_dict = FreqDist(students)
print('The tabulate key-value pairs from FreqDist:')
freq_dict.tabulate()
print('\nThe new list without duplicates:')
print(list(freq_dict), end='\n\n')
The tabulate key-value pairs from FreqDist:
Python R C# Java
2 2 1 1
The new list without duplicates:
['Python', 'R', 'C#', 'Java']
# Using the dict subclass Counter
from collections import Counter
counter_dict = Counter(students)
print(counter_dict, end='\n\n')
print('The new list without duplicates:')
print(list(counter_dict), end='\n\n')
Counter({'Python': 2, 'R': 2, 'C#': 1, 'Java': 1})
The new list without duplicates:
['Python', 'R', 'C#', 'Java']
5. Sử dụng pd.unique
vànp.unique
Cả hai pd.unique
và np.unique
lấy một list có các bản sao và trả về một mảng duy nhất của các phần tử trong list. Các mảng kết quả được chuyển đổi thành list. Trong khi np.unique
sắp xếp các phần tử duy nhất theo thứ tự tăng dần, pd.unique
vẫn duy trì thứ tự của các phần tử trong list.
import numpy as np
import pandas as pd
print('The new list without duplicates using np.unique():')
print(list(np.unique(students)), end='\n\n')
print('\nThe new list without duplicates using pd.unique():')
print(list(pd.unique(students)), end='\n\n')
The new list without duplicates using np.unique():
['C#', 'Java', 'Python', 'R']
The new list without duplicates using pd.unique():
['Python', 'R', 'C#', 'Java']
Ứng dụng: Cửa hàng quà tặng được xem lại
Trong phần này, chúng ta sẽ xem lại minh họa cửa hàng quà tặng của chúng ta. Cửa hàng quà tặng có 50 người. Trung bình có 10 người mua hàng tại cửa hàng mỗi ngày và cửa hàng mở cửa 10 ngày trong tháng. Bạn đã nhận được list list có tên của những khách hàng đã mua hàng của cửa hàng trong tháng trước và nhiệm vụ của bạn là lấy tên của những khách hàng duy nhất để nhận ưu đãi khuyến mại.
# Install the `names` package
!pip install names
# Get package to generate names
import names
import random
random.seed(43)
# Generate names for 50 people in the neighbourhood
names_neighbourhood = [names.get_full_name() for _ in range(50)]
# Import package that randomly select names
from random import choices
# Customers do not have equal probabilities of purchasing from the shop
weights = [random.randint(-20, 20) for _ in range(50)]
# Randomly generate 20 customers that purchased from the store for 10 days
customers_month = [choices(names_neighbourhood, weights=weights, k=10) for _ in range(10)]
Trong khối mã trên, chúng ta đã tạo ngẫu nhiên những khách hàng đã mua hàng từ cửa hàng trong tháng qua dưới dạng list list. Chúng ta muốn có được những khách hàng duy nhất đã mua hàng từ cửa hàng mỗi tháng, vì vậy chúng ta sẽ tạo get_customer_names
chức năng cho nhiệm vụ này.
Chúng ta đã bao gồm các kiểu dữ liệu đầu vào và đầu ra tùy chọn. Python là một ngôn ngữ lập trình được gõ động và xử lý ngầm điều này trong thời gian chạy. Tuy nhiên, rất hữu ích khi hiển thị các kiểu dữ liệu đầu vào và đầu ra cho các cấu trúc dữ liệu phức tạp. Ngoài ra, chúng ta có thể mô tả đầu vào và đầu ra của hàm bằng a docstring
. customers_purchases: List[List[str]]
cho chúng ta biết rằng customers_purchases
tham số là một list chứa các list với các chuỗi và -> List[Tuple[str, int]]
cho chúng ta biết rằng hàm trả về một list chứa các bộ giá trị với một chuỗi và một số nguyên.
from typing import List, Tuple
def get_customer_names(customers_purchases: List[List[str]]) -> List[Tuple[str, int]]:
# Get a single list of all the customers' names from the list of lists
full_list_month = []
for a_day_purchase in customers_purchases:
full_list_month.extend(a_day_purchase)
return Counter(full_list_month).most_common()
customers_list_tuples = get_customer_names(customers_month)
customers_list_tuples
[('Nicole Moore', 14),
('Diane Paredes', 13),
('Mathew Jacobs', 11),
('Katherine Piazza', 10),
('Alvin Cloud', 8),
('Robert Mcadams', 8),
('Roger Lee', 8),
('Becky Hubert', 7),
('Paul Frisch', 7),
('Danielle Mccormick', 5),
('Donna Salvato', 3),
('Sally Thompson', 2),
('Franklin Copeland', 2),
('Linda Sample', 2)]
Tên của khách hàng được tạo ngẫu nhiên - tên của khách hàng có thể khác nếu bạn không sử dụng cùng một seed
giá trị. Tên của những khách hàng duy nhất trong đó customers_list_tuples
xuất phát từ việc đầu tiên chuyển đổi list các bộ giá trị sang một từ điển và sau đó chuyển đổi các khóa từ điển thành một list:
# Unique customers for the previous month
list(dict(customers_list_tuples))
['Nicole Moore',
'Diane Paredes',
'Mathew Jacobs',
'Katherine Piazza',
'Alvin Cloud',
'Robert Mcadams',
'Roger Lee',
'Becky Hubert',
'Paul Frisch',
'Danielle Mccormick',
'Donna Salvato',
'Sally Thompson',
'Franklin Copeland',
'Linda Sample']