Gọi hàm int () trên mọi phần tử danh sách?


183

Tôi có một danh sách với các chuỗi số, như vậy:

numbers = ['1', '5', '10', '8'];

Tôi muốn chuyển đổi mọi thành phần danh sách thành số nguyên, vì vậy nó sẽ trông như thế này:

numbers = [1, 5, 10, 8];

Tôi có thể làm điều đó bằng cách sử dụng một vòng lặp, như vậy:

new_numbers = [];
for n in numbers:
    new_numbers.append(int(n));
numbers = new_numbers;

Nó có phải là xấu xí như vậy? Tôi chắc chắn có một cách pythonic hơn để làm điều này trong một dòng mã. Hãy giúp tôi ra.


1
Bạn đang sử dụng phiên bản Python nào?
Mark Byers

Câu trả lời:



131

Trong Python 2.x một cách tiếp cận khác là sử dụng map:

numbers = map(int, numbers)

Lưu ý: trong Python 3.x maptrả về một đối tượng bản đồ mà bạn có thể chuyển đổi thành danh sách nếu bạn muốn:

numbers = list(map(int, numbers))

11
Trong Python 3.x, maptrả về một iterator thay vì một danh sách, vì vậy nó cần được viết như list(map(int, numbers))thể một danh sách là cần thiết.
kennytm

2
Tôi nghĩ hiện tại phương pháp hiểu danh sách được ưa chuộng hơn một chút.
extraneon

3
@extraneon: Vâng ... hoặc có thể xem xét sử dụng trình tạo thay vì danh sách, tùy thuộc vào mục đích bạn sẽ sử dụng. Ưu điểm của máy phát điện là nếu bạn có thể không cần xem xét tất cả các yếu tố thì bạn sẽ không phải lãng phí thời gian để tính toán chúng trước.
Mark Byers

4
Đo bằng thời gian theo Python 2.7.2: LC: 3.578153133392334, bản đồ: 4.9065070152282715
AJJ

1
@AJJ: mapcó chi phí thiết lập cao hơn, nhưng trên trình thông dịch tham chiếu, nếu hàm biến đổi là hàm tích hợp Python được triển khai trong C, nó có chi phí cho mỗi mục thấp hơn. Thử nghiệm trên đầu vào chỉ có bốn giá trị sẽ không cung cấp thông tin hữu ích về tỷ lệ. Điều đó nói rằng, trong các thử nghiệm của riêng tôi (trên Py2.7.12 và Py3.5.2, sau này với list()gói), Py2 mapđã giành chiến thắng ngay cả đối với bốn yếu tố đầu vào và chỉ thua một lề nhỏ trên Py3; Tôi nghi ngờ các bài kiểm tra của bạn đã bị biến dạng có lợi cho listcomps.
ShadowRanger

21

chỉ là một điểm

numbers = [int(x) for x in numbers]

việc hiểu danh sách là tự nhiên hơn, trong khi

numbers = map(int, numbers)

nhanh hơn.

Có lẽ điều này sẽ không quan trọng trong hầu hết các trường hợp

Đọc hữu ích: LP vs map


6
Không phải là số = map (int, number) sao?
Karan

9

Nếu bạn đang có ý định chuyển các số nguyên đó cho một hàm hoặc phương thức, hãy xem xét ví dụ này:

sum(int(x) for x in numbers)

Cấu trúc này có chủ ý tương tự như cách hiểu danh sách được đề cập bởi adamk. Không có dấu ngoặc vuông, nó được gọi là biểu thức trình tạo và là một cách rất hiệu quả để truyền danh sách các đối số cho một phương thức. Một cuộc thảo luận tốt có sẵn ở đây: Biểu thức máy phát điện so với Danh sách toàn diện


4

Một cách khác để tạo nó trong Python 3:

numbers = [*map(int, numbers)]


1
Bạn có thể giải thích điều này? Tôi không quen với cú pháp đó. Cảm ơn!
abalter

1
Tôi đang sử dụng giải nén danh sách đối số ( docs.python.org/3/tutorial/... )
zhukovgreen

Aha, một con trăn 3 điều. Có vẻ lạ khi có []một danh sách đối số. Và, tôi không biết bạn có thể vượt qua một trình vòng lặp như một danh sách đối số. Tôi đã có ý nghĩ để làm number = list(map(int, numbers)). Nhưng cảm ơn đã giải thích!
abalter

3

Cách khác,

for i, v in enumerate(numbers): numbers[i] = int(v)

6
OP cho biết pythonic
SilentGhost

3
Cách này rất hữu ích nếu bạn chỉ muốn thực hiện thao tác trên một số thành phần trong danh sách. Điều này không liên quan đến câu hỏi trong chủ đề này nhưng có thể có trường hợp khi nó hữu ích
Dikla

1

Tôi nghĩ rằng tôi sẽ củng cố các câu trả lời và hiển thị một số timeitkết quả.

Python 2 hút khá tệ về điều này, nhưng mapnhanh hơn một chút so với hiểu.

Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:42:59) [MSC v.1500 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> setup = """import random
random.seed(10)
l = [str(random.randint(0, 99)) for i in range(100)]"""
>>> timeit.timeit('[int(v) for v in l]', setup)
116.25092001434314
>>> timeit.timeit('map(int, l)', setup)
106.66044823117454

Python 3 nhanh hơn gấp 4 lần, nhưng chuyển đổi mapđối tượng trình tạo thành danh sách vẫn nhanh hơn mức hiểu và tạo danh sách bằng cách giải nén trình maptạo (cảm ơn Artem!) Vẫn nhanh hơn một chút.

Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> setup = """import random
random.seed(10)
l = [str(random.randint(0, 99)) for i in range(100)]"""
>>> timeit.timeit('[int(v) for v in l]', setup)
25.133059591551955
>>> timeit.timeit('list(map(int, l))', setup)
19.705547827217515
>>> timeit.timeit('[*map(int, l)]', setup)
19.45838406513076

Lưu ý: Trong Python 3, 4 phần tử dường như là điểm giao nhau (3 trong Python 2) trong đó khả năng hiểu nhanh hơn một chút, mặc dù việc giải nén trình tạo vẫn nhanh hơn so với các danh sách có nhiều hơn 1 phần tử.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.