2012-02-14 38 views
5

Tôi không chắc chắn nên gọi những gì tôi đang tìm kiếm; vì vậy nếu tôi không tìm thấy câu hỏi này ở nơi khác, tôi xin lỗi. Trong ngắn hạn, tôi đang viết mã python sẽ giao diện trực tiếp với nhân Linux. Dễ dàng nhận các giá trị bắt buộc từ các tệp tiêu đề bao gồm và ghi chúng vào nguồn của tôi:Lập bản đồ hai chiều của Python

IFA_UNSPEC  = 0 
IFA_ADDRESS = 1 
IFA_LOCAL  = 2 
IFA_LABEL  = 3 
IFA_BROADCAST = 4 
IFA_ANYCAST = 5 
IFA_CACHEINFO = 6 
IFA_MULTICAST = 7 

Dễ sử dụng các giá trị này khi xây dựng cấu trúc để gửi tới hạt nhân. Tuy nhiên, chúng hầu như không có sự trợ giúp để giải quyết các giá trị trong các phản hồi từ hạt nhân.

Nếu tôi đặt các giá trị vào dict, tôi sẽ phải quét tất cả các giá trị trong dict để tìm kiếm các khóa cho mỗi mục trong mỗi cấu trúc từ hạt nhân tôi giả sử. Phải có một cách đơn giản hơn, hiệu quả hơn.

Bạn sẽ làm như thế nào? (Cảm thấy tự do để retitle câu hỏi nếu theo cách của mình off)

+1

Thực hiện 2 dicts, một bản đồ theo từng hướng, có thể? Điều này sẽ hiệu quả nếu ánh xạ của bạn không có khả năng thay đổi. –

+0

Tôi nghĩ rằng những gì bạn yêu cầu được trả lời ở đây http://stackoverflow.com/questions/3318625/efficient-bidirectional-hash-table-in-python. Nếu bạn chỉ muốn pythonic, không nhanh: filter (lambda k: a [k] == 3, a) cung cấp cho bạn IFA_LABEL –

+1

@JoelCornett: Vui lòng đăng câu trả lời của bạn làm câu trả lời để có thể bình chọn đúng. –

Trả lời

9

Nếu bạn muốn sử dụng hai dicts, bạn có thể thử này để tạo dict đảo ngược:

b = {v: k for k, v in a.iteritems()} 
+0

Điều này gây ra vấn đề lớn khi các giá trị không phải là duy nhất. Tuy nhiên, từ câu hỏi, có vẻ như các giá trị có thể là duy nhất. Vì vậy, đây là một sử dụng thanh lịch của một nhà xây dựng từ điển. Hơi sạch hơn so với 'dict ((a [k], k) đối với k trong a)'. –

1

Những gì tôi đã kết thúc làm được để lại hằng số các giá trị trong mô đun và tạo ra một dict. Mô-đun là ip_addr.py (giá trị là từ linux/if_addr.h) vì vậy khi xây dựng cấu trúc để gửi tới hạt nhân, tôi có thể sử dụng if_addr.IFA_LABEL và giải quyết phản hồi bằng if_addr.values[2]. Tôi hy vọng đây là thẳng nhất về phía trước nên khi tôi phải xem xét điều này một lần nữa trong một năm + dễ hiểu của nó: p

IFA_UNSPEC  = 0 
IFA_ADDRESS = 1 
IFA_LOCAL  = 2 
IFA_LABEL  = 3 
IFA_BROADCAST = 4 
IFA_ANYCAST = 5 
IFA_CACHEINFO = 6 
IFA_MULTICAST = 7 
__IFA_MAX  = 8 

values = { 
      IFA_UNSPEC : 'IFA_UNSPEC', 
      IFA_ADDRESS : 'IFA_ADDRESS', 
      IFA_LOCAL  : 'IFA_LOCAL', 
      IFA_LABEL  : 'IFA_LABEL', 
      IFA_BROADCAST : 'IFA_BROADCAST', 
      IFA_ANYCAST : 'IFA_ANYCAST', 
      IFA_CACHEINFO : 'IFA_CACHEINFO', 
      IFA_MULTICAST : 'IFA_MULTICAST', 
      __IFA_MAX  : '__IFA_MAX' 
     } 
2

giải pháp của bạn lá rất nhiều công việc làm người lặp đi lặp lại tạo ra các tập tin. Đó là một nguồn lỗi (bạn thực sự phải viết mỗi tên ba lần). Nếu bạn có một tập tin mà bạn cần phải cập nhật những người theo thời gian (như, khi phát hành hạt nhân mới đi ra), bạn được mệnh để bao gồm một lỗi sớm hay muộn. Trên thực tế, đó chỉ là một cách nói dài, giải pháp của bạn vi phạm DRY.

tôi sẽ thay đổi giải pháp của bạn để một cái gì đó như thế này:

IFA_UNSPEC  = 0 
IFA_ADDRESS = 1 
IFA_LOCAL  = 2 
IFA_LABEL  = 3 
IFA_BROADCAST = 4 
IFA_ANYCAST = 5 
IFA_CACHEINFO = 6 
IFA_MULTICAST = 7 
__IFA_MAX  = 8 

values = {globals()[x]:x for x in dir() if x.startswith('IFA_') or x.startswith('__IFA_')} 

Đây là dict values được tạo ra tự động. Bạn có thể muốn (hoặc phải) thay đổi điều kiện trong câu lệnh if ở đó, theo bất kỳ điều gì khác có trong tệp đó. Có thể một cái gì đó như sau. Phiên bản đó sẽ lấy đi sự cần thiết phải liệt kê các tiền tố trong câu lệnh if, nhưng nó sẽ thất bại nếu bạn có các thứ khác trong tệp.

values = {globals()[x]:x for x in dir() if not x.endswith('__')} 

Bạn có thể làm điều gì đó tinh vi hơn ở đó, ví dụ: kiểm tra các giá trị lặp lại vô tình.

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