2017-09-19 30 views
8

मैं एक एपीआई के कई अंतराल का उपभोग कर रहा हूं जो डेटा लौटने में बहुत वर्बोज़ है। मैं इस डेटा का एक सबसेट कहीं और कोड के दूसरे हिस्से में प्रदान करना चाहता हूं।केवल कुछ निश्चित वस्तुओं के साथ एक नया शब्दकोश वापस करने के लिए पाइथन 3 नेस्टेड शब्दकोश को मास्क कैसे करें?

मान लीजिए मैं इस तरह कई शब्दकोशों (जो मैं के माध्यम से लूप करने की योजना है और फिल्टर) दिया हूँ:

asset = { 
    'id': 1, 
    'name': 'MY-PC', 
    'owner': 'me', 
    'location': 'New York City', 
    'model': { 
     'id': 1, 
     'name': 'Surface', 
     'manufacturer': { 
      'id': 1, 
      'name': 'Microsoft' 
     } 
    } 
} 

मैं एक समारोह है कि में कि शब्दकोश ले जाएगा बनाने के लिए एक "मुखौटा" के साथ चाहते हैं जो केवल स्वीकृत वस्तुओं का एक नया शब्दकोश बनाने के लिए इस्तेमाल किया जाएगा।

mask = { 
    'id': True, 
    'name': True, 
    'model': { 
     'id': True, 
     'name': True, 
     'manufacturer': { 
      'name': True 
     } 
    } 
} 

समारोह तो यह लौटना चाहिए:

mask = { 
    'id': 1, 
    'name': 'MY-PC', 
    'model': { 
     'id': 1, 
     'name': 'Surface', 
     'manufacturer': { 
      'name': 'Microsoft' 
     } 
    } 
} 

वहाँ कुछ पहले से ही निर्मित है (हालांकि, मैं जो कुछ भी प्रारूप जिसके परिणामस्वरूप कोड सबसे संक्षिप्त बनाता है के साथ काम कर सकते हैं) यह एक उदाहरण मुखौटा हो सकता है पायथन 3 में जो इस में सहायता करने में मदद करेगा? ऐसा लगता है कि मुझे इसे मैन्युअल रूप से करना है, तो यह काफी बदसूरत हो जाएगा। मुझे itertools.compress मिला, लेकिन ऐसा लगता है कि यह सूचियों के लिए है और शब्दकोशों की जटिलता को संभाल नहीं पाएगा।

def copy(asset, result, mask): 
    for key_name, value in mask.items(): 
     if value == True: 
      result[key_name] = asset[key_name] 
     else: 
      result[key_name] = x = {} 
      copy(asset[key_name], x, value) 

y = {} 
copy(asset, y, mask) 
+0

क्या आपने ['jq (1)'] (https://stedolan.github.io/jq/) के बारे में सुना है? – o11c

+0

ywhat तब होना चाहिए जब मास्क कुंजियों के पास मेल खाने वाली डेटा कुंजी न हो? –

उत्तर

3

आप रिकर्सिवली का चयन केवल मुख्य में संगत मानों से नकाब से एक नई शब्दावली का निर्माण कर सकते हैं:

2

यह प्रत्यावर्तन उपयोग करने के लिए एक अच्छा मौका हो सकता है, यहां कुछ नमूना कोड मैं परीक्षण नहीं किया है dict:

def prune_dict(dct, mask): 
    result = {} 
    for k, v in mask.items(): 
     if isinstance(v, dict): 
      value = prune_dict(dct[k], v) 
      if value: # check that dict is non-empty 
       result[k] = value 
     elif v: 
      result[k] = dct[k] 
    return result 

print(prune_dict(asset, mask)) 

{'id': 1, 
'model': {'id': 1, 'manufacturer': {'name': 'Microsoft'}, 'name': 'Surface'}, 
'name': 'MY-PC'} 
0

यह शायद एक पुनरावर्ती समारोह होगा। mask = ["id", "name", "model.id", "model.name", "model.manufacturer.name"]

उसके बाद, आप पहले ही प्रविष्टियों को नकाब में नाम हैं रखना चाहते हैं:: इसके अलावा, मुखौटा के लिए, मैं इस प्रारूप की सिफारिश

def filterstage1(dictionary, mask): 
    result = {} 
    for key in dictionary: 
     if isinstance(dictionary[key], dict): 
      newmask = [maskname[mask.find(".") + 1:] for maskname in mask if maskname.startswith(key + ".")] 
      result[k] = filterstage1(dictionary[key], newmask) 
     elif key in mask: 
      result[key] = dictionary[key] 
    return result 

फिर, क्या है या नहीं आप चाहते हैं पर निर्भर करता है दूर करने के लिए

def filterstage2(dictionary, mask): 
    result = {} 
    for key in dictionary: 
     if not (isinstance(dictionary[key], dict) and dictionary[key] == {} and key not in mask): 
      result[key] = dictionary[key] 

अंतिम कोड: filterstage2(filterstage1(dictionary, mask), mask)-उप शब्दकोशों कि मुखौटा में नहीं थे और कोई उसके उप-तत्व था, तो आप दूसरे चरण में शामिल कर सकते हैं। यदि आप चाहें तो आप दोनों चरणों को एक साथ जोड़ सकते हैं।

+0

पीएस अन्य उत्तरों देखें; यह समाधान शायद उत्पादन कोड के लिए बहुत अच्छा नहीं है: पी – HyperNeutrino

संबंधित मुद्दे