2016-03-07 26 views
5

tôi có một danh sáchLàm cách nào để so sánh danh sách bằng Python?

a = [1.0, 2.0, 2.1, 3.0, 3.1, 4.2, 5.1, 7.2, 9.2] 

tôi muốn so sánh danh sách này với danh sách khác nhưng tôi cũng muốn trích xuất các thông tin liên quan đến nội dung danh sách trong order.All số danh sách khác có những yếu tố đó đều giống như a.

Vì vậy, tôi đã cố gắng này

a = [1.0, 2.0, 2.1, 3.0, 3.1, 4.2, 5.1, 7.2, 9.2] 
b = [1, 2, 3, 4, 5, 6, 7, 8, 9] 
print dict(zip(a,b)) 

a1=[2.1, 3.1, 4.2, 7.2] 

tôi muốn so sánh a1 với a và trích xuất dict giá trị [3, 5, 6, 8].

Trả lời

6

Chỉ cần lặp qua a1 và xem nếu có một phím tương ứng trong từ điển bạn đã tạo:

mapping = dict(zip(a, b)) 
matches = [mapping[value] for value in a1 if value in mapping] 

Demo:

>>> a = [1.0, 2.0, 2.1, 3.0, 3.1, 4.2, 5.1, 7.2, 9.2] 
>>> b = [1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> a1 = [2.1, 3.1, 4.2, 7.2] 
>>> mapping = dict(zip(a, b)) 
>>> [mapping[value] for value in a1 if value in mapping] 
[3, 5, 6, 8] 

Tuy nhiên, đưa vào tài khoản mà bạn đang sử dụng điểm nổi số. Bạn có thể không khớp chính xác các giá trị, vì các số dấu phẩy động là các giá trị xấp xỉ nhị phân cho các giá trị thập phân; giá trị 2.999999999999999 (15 nines) ví dụ, có thể được trình bày bởi các chức năng Python str() như 3.0, nhưng là không bằng-3.0:

>>> 2.999999999999999 
2.999999999999999 
>>> str(2.999999999999999) 
'3.0' 
>>> 2.999999999999999 == 3.0 
False 
>>> 2.999999999999999 in mapping 
False 

Nếu đầu vào của bạn liệt kê a được sắp xếp, bạn có thể sử dụng math.isclose() function (hoặc một backport của nó), cùng với bisect module để giữ phù hợp với hiệu quả:

import bisect 
try: 
    from math import isclose 
except ImportError: 
    def isclose(a, b, rel_tol=1e-09, abs_tol=0.0): 
     # simplified backport, doesn't handle NaN or infinity. 
     if a == b: return True 
     return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol) 

result = [] 
for value in a1: 
    index = bisect.bisect(a, value) 
    if index and isclose(a[index - 1], value): 
     result.append(b[index - 1]) 
    elif index < len(a) and isclose(a[index], value): 
     result.append(b[index]) 

này kiểm tra lên đến hai giá trị từ a mỗi giá trị đầu vào; một giá trị được đảm bảo bằng hoặc thấp hơn (tại index - 1) và giá trị tiếp theo, cao hơn. Đối với mẫu của bạn a, giá trị 2.999999999999999 được chia nhỏ thành chỉ mục 3, giữa 2.13.0. Vì isclose(3.0, 2.999999999999999) là đúng, điều đó sẽ vẫn cho phép bạn ánh xạ giá trị đó đến 4 trong b.

+0

Peters Thanks.The số trong danh sách là kết quả của việc thực thi mã FORTRAN, được định dạng bằng f11.5.Vì vậy, tôi nghĩ rằng phiên bản đơn giản sẽ đủ! –

+0

Phải, nếu bạn có * chuỗi *, sau đó bạn vấp phải vấn đề khá độc đáo. –

Các vấn đề liên quan