2010-03-08 51 views
6

Tôi có từ điển python có khóa là chuỗi và giá trị là đối tượng.Python: Nhận giá trị (đối tượng) từ từ điển đối tượng trong đó một trường của đối tượng khớp với giá trị (hoặc điều kiện)

Ví dụ, một đối tượng với một chuỗi và một int

class DictItem: 
    def __init__(self, field1, field2): 
     self.field1 = str(field1) 
     self.field2 = int(field2) 

và từ điển:

myDict = dict() 
myDict["sampleKey1"] = DictItem("test1", 1) 
myDict["sampleKey2"] = DictItem("test2", 2) 
myDict["sampleKey3"] = DictItem("test3", 3) 

nào là/cách hiệu quả nhất tốt nhất để có được những mục từ điển mà có " field2 "field> = 2?

Ý tưởng là tạo ra một "tiểu từ điển" (một danh sách sẽ làm quá) chỉ với các mục trong đó field2> = 2 (trong ví dụ này sẽ như thế nào):

{ 
    "sampleKey2": { 
     "field1" : "test2", 
     "field2": 2 
    }, 
    "sampleKey3": { 
     "field1" : "test3", 
     "field2": 3 
    } 
} 

Có cách tốt hơn là đi qua tất cả các yếu tố từ điển và kiểm tra tình trạng? Có thể sử dụng chức năng itemgetters và lambda?

Cảm ơn bạn!

PS: Tôi đang sử dụng python2.4, chỉ trong trường hợp nó có liên quan

+0

Cảm ơn tất cả !! Đó là thông tin rất hữu ích :) – BorrajaX

Trả lời

8

Để thực hiện một dict từ của bạn dict,

subdict = dict((k, v) for k, v in myDict.iteritems() if v.field2 >= 2) 
+0

Cuối cùng tôi chọn giải pháp này :) Cảm ơn bạn !! – BorrajaX

+1

@BorrajaX, vậy tại sao không chấp nhận câu trả lời (với biểu tượng dấu kiểm dưới số lớn)? Đó là nghi thức cơ bản của SO: cảm ơn rất tốt, nhưng sự chấp nhận là điều quan trọng! –

+0

.. Ohhh ... Tôi không biết cách làm việc này! (Đây là bài viết đầu tiên của tôi ở đây) – BorrajaX

4
mySubList = [dict((k,v) for k,v in myDict.iteritems() if v.field2 >= 2)] 

Tài liệu:

list-comprehensions, iteritems()

+0

ngoại trừ ông muốn một dict, không phải là một danh sách ... –

+4

"một danh sách sẽ làm quá" – bernie

3

Bạn nên giữ hồ sơ khác nhau của bạn - đó là "DicItem" trường hợp - bên trong danh sách. Biểu thức máy phát/danh sách sau đó có thể lọc kết quả mong muốn của bạn một cách dễ dàng.

data = [ 
    DictItem("test1", 1), 
    DictItem("test2", 2), 
    DictItem("test3", 3), 
    DictItem("test4", 4), 
] 

và sau đó:

results = [item for item in data if item.field2 >= 2] 

này, tất nhiên, tạo ra một bộ lọc tuyến tính. Nếu bạn cần nhiều hơn tốc độ tuyến tính cho một số truy vấn của bạn, đối tượng container cho thanh ghi - trong trường hợp này là "danh sách" phải là một lớp chuyên biệt có thể tạo các chỉ mục của dữ liệu ở đó, giống như một DBMS. chỉ mục. Điều này có thể được thực hiện dễ dàng để tạo ra một lớp học từ "danh sách" và ghi đè các phương pháp "append", "insert", "__getitem__", "__delitem__""pop"."

Nếu bạn cần điều này cho một ứng dụng hồ sơ cao, tôi khuyên bạn nên xem xét một số hướng đối tượng hệ thống DB cho Python trên mạng, như ZODB và những người khác.

2

ý tưởng là tạo ra một "tiểu từ điển" (một danh sách sẽ làm quá)

Nếu bạn muốn có một danh sách mà bạn có thể sử dụng filter (hoặc itertools.ifilter):

result_list = filter(lambda x: x.field2 > 2, mydict.values()) 
0

'Hiệu quả nhất' sẽ phụ thuộc vào tần suất nội dung từ điển thay đổi so với tần suất bạn thực hiện tra cứu.

Nếu từ điển thay đổi thường xuyên và bạn thực hiện tra cứu ít thường xuyên hơn thì phương pháp hiệu quả nhất sẽ đi qua vòng lặp và chọn các đối tượng khớp với tiêu chí, sử dụng mã mà Adam Bernier đăng.

Nếu từ điển không thay đổi nhiều và bạn thực hiện rất nhiều tra cứu thì có thể nhanh hơn để tạo một hoặc nhiều từ điển nghịch đảo, ví dụ: một ánh xạ các giá trị "field2" vào danh sách các đối tượng có giá trị đó.

Ngoài ra nếu bạn đang đi để được làm các truy vấn phức tạp, bạn có thể đặt tất cả các dữ liệu vào một cơ sở dữ liệu sqllite trong bộ nhớ và để cho SQL loại nó ra, có lẽ thông qua một ORM như SQLAlchemy

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