2017-09-19 66 views
8

Geri döndürdüğü verilerde çok ayrıntılı bir API'nın birkaç uç noktasını tüketiyorum. Bu verilerin bir alt kümesini başka bir yerde başka bir kod parçasına vermek istiyorum. Birkaç (I döngü planlamak ve filtreyi) böyle sözlükleri verilen am varsayalımYeni bir sözlüğü yalnızca belirli öğelerle döndürmek için Python 3 iç içe geçmiş sözlüğü nasıl maskelenir?

:

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

Ben bir "maske" ile birlikte, bu sözlüğü alacak bir işlev oluşturmak istediğiniz sadece izin verilen öğelerin yeni bir sözlüğünü oluşturmak için kullanılacaktır.

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

fonksiyonu o zaman bu dönmelidir:

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

çoktan inşa şey var mı Bu örnek bir maske olabilir (gerçi ben çıkan kod en özlü ediyorsa onu biçimi ile çalışabilir) Buna yardımcı olacak Python 3'e mi? Bunu el ile yapmam gerekiyor gibi görünüyor, çok çirkin bir şekilde çabuk olacak. itertools.compress'u buldum, ancak listelerde olduğu gibi görünüyor ve sözlüklerin karmaşıklığını ele almıyor.

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/) 'yi duydunuz mu? – o11c

+0

Maske tuşları eşleşen veri anahtarına sahip olmadığında ne olur? –

cevap

3

Sen damgası yalnızca ana karşılık gelen değerlerinin seçerek maske yeni dicti inşa edebilirsiniz:

2

Bu Özyinelemeyi kullanmak için iyi bir şans olurdu, burada ben test etmedim bazı örnek kod 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

Bu muhtemelen bir özyinelemeli fonksiyon olacaktır.

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 

Sonra isteyip istemediğinize bağlı olarak kaldırmak için: İlk maskeli adlandırılır sadece girdileri devam ederdim, sonra mask = ["id", "name", "model.id", "model.name", "model.manufacturer.name"]

: Ayrıca, maske, ben bu biçimi tavsiye

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] 

Final kodu: filterstage2(filterstage1(dictionary, mask), mask) maske değildi ve hiçbir alt öğeleri vardı alt sözlükleri, ikinci aşamayı içerebilir. İsterseniz iki aşamayı birleştirebilirsiniz.

+0

P.S. Diğer cevaplara bakın; Bu çözüm muhtemelen üretim kodu için çok iyi değil: P – HyperNeutrino

İlgili konular