2010-11-19 37 views
8

Tôi có một dict mà tôi muốn chuyển đổi trong JSON bằng cách sử dụng simplejson.Làm thế nào để đảm bảo rằng một phím dict python là chữ thường?

Làm cách nào để đảm bảo rằng tất cả các khóa của dict đều là chữ thường?

{ 
     "DISTANCE": 17.059918745802999, 
     "name": "Foo Bar", 
     "Restaurant": { 
      "name": "Foo Bar", 
      "full_address": { 
       "country": "France", 
       "street": "Foo Bar", 
       "zip_code": "68190", 
       "city": "UNGERSHEIM" 
      }, 
      "phone": "+33.389624300", 
      "longitude": "7.3064454", 
      "latitude": "47.8769091", 
      "id": "538" 
     }, 
     "price": "", 
     "composition": "", 
     "profils": {}, 
     "type_menu": "", 
     "ID": "" 
    }, 

EDIT: Cảm ơn tất cả đã xem câu hỏi của tôi, tôi rất tiếc tôi không giải thích chi tiết lý do tôi muốn điều này. Đó là để vá JSONEmitter của django-piston.

+2

Để đảm bảo chúng là chữ thường, chúng phải là chữ thường. Tạo một dict với các phím chữ thường. –

+0

Bạn có ý gì bằng cách "đảm bảo"? Bạn có và dict hiện có và bạn có muốn kiểm tra xem tất cả các phím là chữ thường? Hoặc chuyển đổi tất cả thành chữ thường? Hay bạn muốn tạo ra một loại dict chỉ cho phép các phím chữ thường (khi chèn chúng)? – Jordi

+0

Như bạn có thể thấy trong ví dụ, một số phím không phải là chữ thường. Tôi muốn chắc chắn rằng mọi khóa JSON đều là chữ thường. – Natim

Trả lời

21
>>> d = {"your": "DATA", "FROM": "above"} 
>>> dict((k.lower(), v) for k, v in d.iteritems()) 
{'from': 'above', 'your': 'DATA'} 
>>> def lower_keys(x): 
... if isinstance(x, list): 
...  return [lower_keys(v) for v in x] 
... elif isinstance(x, dict): 
...  return dict((k.lower(), lower_keys(v)) for k, v in x.iteritems()) 
... else: 
...  return x 
... 
>>> lower_keys({"NESTED": {"ANSWER": 42}}) 
{'nested': {'answer': 42}} 
+0

Tôi chỉ chọn ra rằng bạn muốn các cảnh sát và danh sách lồng nhau được xử lý đặc biệt từ câu trả lời của bạn; thông thường tôi sẽ xử lý điều này ở một cấp độ khác. –

+3

Trên python 3 bạn có thể sử dụng hiểu và sẽ không cần 'dict (...)' -> 'd = {k.lower(): v cho k, v trong d.items()}' – Delblanco

2

Đây là giải pháp của tôi:

def lower_key(in_dict): 
    if type(in_dict) is dict: 
     out_dict = {} 
     for key, item in in_dict.items(): 
      out_dict[key.lower()] = lower_key(item) 
     return out_dict 
    elif type(in_dict) is list: 
     return [lower_key(obj) for obj in in_dict] 
    else: 
     return in_dict 
+0

Giải pháp đệ quy tốt, để xử lý vấn đề sau "thực tế". – ThomasH

4

Vì bạn đã không được đề cập rõ ràng những gì bạn muốn làm:

Chuyển đổi tất cả các phím chữ thường:

>>> y = dict((k.lower(), v) for k, v in x.iteritems()) 

Kiểm tra khóa:

>>> for k in x.iterkeys(): 
    if k.islower(): 
     print k, 'True' 
    else: 
     print k, 'False' 
+0

vấn đề với .iteritems() và .iterkeys() là chúng không đệ quy. – ThomasH

8

Đây là một giải pháp mà cấm thiết lập một phím chữ thường:

class LowerCaseDict(dict): 
    def __setitem__(self, key, val): 
     if not key.islower(): 
      raise TypeError, "%s key must be lowercase" % key 
     dict.__setitem__(self, key, val) 

ld = LowerCaseDict() 
ld['g']='g' 
+6

Hoặc, chỉ có '__setitem__' làm' dict .__ setitem __ (self, key.lower(), val) '. Vấn đề với cách tiếp cận này nói chung là hàm tạo và '.update' không sử dụng __setitem__ - bạn sẽ cần phải làm việc xung quanh đó, hoặc' LowerCaseDict ({'Foo': 1, 'bar': 2}) ' sẽ không hoạt động như mong đợi (sẽ không hạ thấp nó theo cách của tôi hoặc sẽ không tăng TypeError theo cách của bạn). –

+0

Bạn cũng phải đảm bảo cũng sử dụng LowerCaseDict cho mọi mệnh lệnh lồng nhau. – ThomasH

+0

@Chris Nhận xét tuyệt vời. – ThomasH

2

Nếu bạn chỉ muốn séc nếu họ đang tất cả chữ thường (từ ngữ của bạn, sử dụng "đảm bảo", không rõ ràng, nhưng tôi nghi ngờ điều này không phải là những gì bạn muốn), bạn có thể làm điều đó gọn trong một dòng:

all(k.islower() for k in x.iterkeys()) 
2

đây là một giải pháp hoàn chỉnh

from requests import CaseInsensitiveDict 

Hoặc nếu bạn muốn xem mã:

class CaseInsensitiveDict(dict): 

    """Basic case insensitive dict with strings only keys.""" 

    proxy = {} 

    def __init__(self, data): 
     self.proxy = dict((k.lower(), k) for k in data) 
     for k in data: 
      self[k] = data[k] 

    def __contains__(self, k): 
     return k.lower() in self.proxy 

    def __delitem__(self, k): 
     key = self.proxy[k.lower()] 
     super(CaseInsensitiveDict, self).__delitem__(key) 
     del self.proxy[k.lower()] 

    def __getitem__(self, k): 
     key = self.proxy[k.lower()] 
     return super(CaseInsensitiveDict, self).__getitem__(key) 

    def get(self, k, default=None): 
     return self[k] if k in self else default 

    def __setitem__(self, k, v): 
     super(CaseInsensitiveDict, self).__setitem__(k, v) 
     self.proxy[k.lower()] = k 
Các vấn đề liên quan