2017-07-13 65 views
0

[Python 2.7]Python鏈接get()方法與列表元素JSON內

我有一個JSON源,並不總是返回所需的鍵的完整列表。我使用鏈接的gets()來解決這個問題。

d = {'a': {'b': 1}} 

print(d.get('a', {}).get('b', 'NA')) 
print(d.get('a', {}).get('c', 'NA')) 

>>> 1 
>>> NA 

但是,有些類型的字典在列表中:

d = {'a': {'b': [{'c': 2}]}} 

print(d['a']['b'][0]['c']) 

>>> 2 

我不能使用get()方法,考慮到這一點,因爲列表不支持的get()屬性:

d.get('a', {}).get('b', []).get('c', 'NA') 

>>> AttributeError: 'list' object has no attribute 'get' 

除了俘獲數百潛在KeyErrors的,有()以類似的方式與鏈GET(構建體上文)以考慮到潛在的缺失['c']優選的方法?

+1

'.get('b',[{}])[0]',也許? – jonrsharpe

+0

_「除了捕獲數百個潛在的KeyErrors,[...]」_有什麼錯誤的嘗試:...除了:'? –

+0

@jonrsharpe:謝謝。這正是我所期待的。請考慮加入這個問題作爲答案。 – DaveL17

回答

2

我@stovfl同意,編寫自己的查找功能是要走的路。雖然,我不認爲遞歸實現是必要的。以下應工作不夠好:

def nested_lookup(obj, keys, default='NA'): 
    current = obj 
    for key in keys: 
     current = current if isinstance(current, list) else [current] 
     try: 
      current = next(sub[key] for sub in current if key in sub) 
     except StopIteration: 
      return default 
    return current 


d = {'a': {'b': [{'c': 2}, {'d': 3}]}} 

print nested_lookup(d, ('a', 'b', 'c')) # 2 
print nested_lookup(d, ('a', 'b', 'd')) # 3 
print nested_lookup(d, ('a', 'c'))  # NA 

類的做法似乎並不大,因爲你將要產生很多不必要的對象,如果你曾經試圖查找這不是一個節點一片葉子,那麼你將結束一個自定義對象而不是實際的節點對象。

+0

謝謝你。它運作良好,看起來很簡單。即使@ stovfl的第二個例子也適用,我會接受這個答案。我無法自己想出一個令人滿意的功能,因此無法實施Rawing正在將其轉變爲功能的建議。 – DaveL17

2

Question: I can't use a get() ... because lists don't support the get().

  1. 您可以實現自己的list.get(),例如:

    class myGET(object): 
        def __init__(self, data): 
         if isinstance(data, dict): 
          self.__dict__.update(data) 
         if isinstance(data, list): 
          for d in data: 
           self.__dict__.update(d) 
    
        def get(self, key, default=None): 
         if hasattr(self, key): 
          _attr = object.__getattribute__(self, key) 
          if isinstance(_attr, (list, dict)): 
           return myGET(_attr) 
          else: 
           return _attr 
         else: 
          return default 
    
    d = {'a': {'b': [{'c': 2}]}} 
    myGET(d).get('a', {}).get('b', []).get('c', 'NA') 
    >>> 2 
    
    myGET(d).get('a', {}).get('b', []).get('d', 'NA') 
    >>> NA 
    
  2. 一個遞歸解決方案,無需鏈接,例如:

    def get(_dict, subkey, default): 
        def _get(_dict, key, deep): 
         if key == subkey[deep]: 
          if deep == len(subkey) - 1: 
           return _dict 
          else: 
           return _get(_dict, None, deep + 1) 
    
         elif isinstance(_dict, dict): 
          for k in _dict: 
           match = _get(_dict[k], k, deep) 
           if match: return match 
    
         elif isinstance(_dict, list): 
          for e in _dict: 
           match = _get(e, None, deep) 
           if match: return match 
    
        if not isinstance(subkey, (tuple, list)): 
         subkey = (subkey) 
    
        _r = _get(_dict, None, 0) 
        if not _r: return default 
        else:  return _r 
    
    get(d, 'c', 'NA') 
    >>> 2 
    
    get(d, 'd', 'NA') 
    >>> NA 
    
    # get a inside b 
    d = {'a': {'b': [{'a': 3}, {'c': 2}]}} 
    get(d, ('b', 'a'), 'NA') 
    >>> 3 
    

與Python測試:3.4.2和2.7.9

+0

謝謝你。你的第一個例子給了我一個例外,但第二個例子很好。文件「無標題文本21」,第23行,在中 myGET(d).get('a',{})。get(' '',']'。get('c','NA') 文件「untitled text 21」,in line 14,in _attr = object .__ getattribute __(self,key) AttributeError:'instance'object has沒有屬性'a'' – DaveL17

+0

@ DaveL17:是的2.7問題,缺失子類'class myGET(object):',fixed。 – stovfl