2009-07-29 31 views
11

Tôi đang tái cấu trúc một hàm, với một chuỗi các điểm cuối xác định ngầm định, kiểm tra xem một số có được bao gồm trong khoảng không và sau đó trả về tương ứng (không liên quan đến bất kỳ cách tính toán nào)). Mã mà bây giờ là xử lý công việc là:Python: Lập bản đồ từ các khoảng thời gian đến các giá trị

if p <= 100: 
    return 0 
elif p > 100 and p <= 300: 
    return 1 
elif p > 300 and p <= 500: 
    return 2 
elif p > 500 and p <= 800: 
    return 3 
elif p > 800 and p <= 1000: 
    return 4 
elif p > 1000: 
    return 5 

Đó là IMO khá khủng khiếp, và thiếu ở chỗ cả hai khoảng thời gian và giá trị trả về là mã hóa cứng. Có thể sử dụng bất kỳ cấu trúc dữ liệu nào.

Trả lời

35
import bisect 
bisect.bisect_left([100,300,500,800,1000], p) 
+0

+1 Tôi thích điều này. Bạn học được điều gì mới mỗi ngày. – kjfletch

+0

+1: không thể tin được! –

+1

Thực sự ấn tượng. Siêu sạch, và tôi cũng tin rất nhanh. Nó cũng có thể dễ dàng mở rộng trong trường hợp người ta cần một thứ tự không tự nhiên hoặc thứ gì đó ngược lại, giống như một chuỗi: nhập khẩu bisect n = bisect.bisect_left ([100,300,500,800,1000], p) a = ["vắng mặt", "thấp", "trung bình", "cao", "rất cao", "cực"] a [n] – Agos

0

Hãy thử một cái gì đó dọc theo dòng:

d = {(None,100): 0, 
    (100,200): 1, 
    ... 
    (1000, None): 5} 
value = 300 # example value 
for k,v in d.items(): 
    if (k[0] is None or value > k[0]) and (k[1] is None or value <= k[1]): 
     return v 
3

Bạn có thể thử một mất về điều này:

def check_mapping(p): 
    mapping = [(100, 0), (300, 1), (500, 2)] # Add all your values and returns here 

    for check, value in mapping: 
     if p <= check: 
      return value 

print check_mapping(12) 
print check_mapping(101) 
print check_mapping(303) 

sản xuất:

0 
1 
2 

Như mọi khi bằng Python, sẽ có bất kỳ cách nào tốt hơn để làm điều đó.

+0

Không tính đến trường hợp p> 1000! – stefanw

+0

Đó là lý do tại sao tôi chỉ định: "Bạn có thể thử thực hiện điều này" – kjfletch

+0

Câu cuối cùng là mỉa mai, xem xét triết lý python của việc tốt nhất chỉ có một cách rõ ràng để làm điều gì đó. – sykora

0
def which_interval(endpoints, number): 
    for n, endpoint in enumerate(endpoints): 
     if number <= endpoint: 
      return n 
     previous = endpoint 
    return n + 1 

Vượt qua điểm cuối của bạn như là một danh sách trong endpoints, như thế này:

which_interval([100, 300, 500, 800, 1000], 5) 

Edit:

Trên đây là một tìm kiếm tuyến tính. Câu trả lời của Glenn Maynard sẽ có hiệu suất tốt hơn, vì nó sử dụng thuật toán bisection.

+0

Mất chữ "trước"; nó khá dư thừa. –

+0

Vâng, bạn nói đúng, tôi đoán mã ban đầu "lấy cảm hứng" tôi để sử dụng nó. BTW, sử dụng của bạn của mệnh lệnh có thể âm thanh một chút thô lỗ với một số. – Steef

+0

@Steef: Bạn có thể muốn xem xét một đề nghị khiêm nhường rằng bạn có thể giải trí của bạn trả lời câu trả lời của bạn, lưu ý rằng ** câu trả lời của bạn vẫn bao gồm một dòng dự phòng của mã **, và trong sự viên mãn của thời gian, excise như nhau. –

0

Một cách khác ...

def which(lst, p): 
    return len([1 for el in lst if p > el]) 

lst = [100, 300, 500, 800, 1000] 
which(lst, 2) 
which(lst, 101) 
which(lst, 1001) 
3

Nó thực sự là khá khủng khiếp. Nếu không có một yêu cầu không có hardcoding, nó cần phải có được viết như thế này:

if p <= 100: 
    return 0 
elif p <= 300: 
    return 1 
elif p <= 500: 
    return 2 
elif p <= 800: 
    return 3 
elif p <= 1000: 
    return 4 
else: 
    return 5 

Dưới đây là ví dụ về việc tạo ra một chức năng tra cứu, cả hai tuyến tính và sử dụng tìm kiếm nhị phân, với yêu cầu không hardcodings hoàn thành, và một cặp vợ chồng kiểm tra sanity trên hai bảng:

def make_linear_lookup(keys, values): 
    assert sorted(keys) == keys 
    assert len(values) == len(keys) + 1 
    def f(query): 
     return values[sum(1 for key in keys if query > key)] 
    return f 

import bisect 
def make_bisect_lookup(keys, values): 
    assert sorted(keys) == keys 
    assert len(values) == len(keys) + 1 
    def f(query): 
     return values[bisect.bisect_left(keys, query)] 
    return f 
+0

Tôi thích cái này tốt hơn so với người có nhiều phiếu bầu nhất vì hình thức tổng quát/không được mã hóa nhiều hơn và vì nó có chiều sâu hơn. – JAB

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