2017-12-19 14 views
1

私はAPIを複数回呼び出して、結果をCSVに書きます。それは多くのスペースを占めているためdictの要素にアクセスする最もPythonの方法

city = data['property'][0]['address']['locality'] 
zip_code = data['property'][0]['address']['postal1'] 
county = data['property'][0]['area']['countrysecsubd'] 
condition = data['property'][0]['building']['construction']['condition'] 
roof = data['property'][0]['building']['construction']['roofcover'] 
bathrooms = data['property'][0]['building']['rooms']['bathstotal'] 
bedrooms = data['property'][0]['building']['rooms']['beds'] 
total_number_of_rooms = data['property'][0]['building']['rooms']['roomsTotal'] 
square_footage = data['property'][0]['building']['size']['bldgsize'] 
year_built = data['property'][0]['summary']['yearbuilt'] 
number_of_stories = data['property'][0]['building']['summary']['levels'] 
lot_size1 = data['property'][0]['lot']['lotsize1'] 
lot_size2 = data['property'][0]['lot']['lotsize2'] 
latitude = data['property'][0]['location']['latitude'] 
longitude = data['property'][0]['location']['longitude'] 

dictの構造はペーストビンにhereです:私はdictからデータを抽出するために、次のコードを持っています。

少ないコードで同じ結果を得るにはどうすればよいですか?

+2

私は考えることができる唯一のことは、短いエイリアス '小道具は=データ[「プロパティを」]作成され、[0]' – Julien

+1

あなたはそれがきれいしかし_less作ることができます@Julienの提案に従い、[this](https://stackoverflow.com/a/32107024/1112586)や[this](https://stackoverflow.com/a/23689767/1112586)のようなことをして、pythonic_ 。つまり、これは辞書を扱う実際に非標準的な方法であり、他の開発者を混乱させる可能性があります。 – SCB

答えて

1

あなたが行っている方法は「Pythonic」です。しかし、他の選択肢があり、キーがオブジェクト(またはサブオブジェクト)属性であるかのようにキーを使用することです。多かれ少なかれPythonicかどうかは、見る人の目の前にあります。足場が設置されたら、間違いなく入力が少なくて済みますし、読めるようになっています。

そのようなものを実装する1つの方法は、のdictサブクラスを作成することです。クラスが定義されたら、その中の最も外側のサブディクショナリとすべてのサブディクショナリをAttrDictインスタンスに変換する必要があります。

ここで私が何を意味するかを示すコードです:

import json 

class AttrDict(dict): 
    def __init__(self, *args, **kwargs): 
     super(AttrDict, self).__init__(*args, **kwargs) 
     self.__dict__ = self 


def convert(d): 
    """ Convert dict "d" and all nested dictionaries in it into AttrDicts. """ 
    def _decode_dict(a_dict): 
     return AttrDict(a_dict) # Turn each dictionary into an AttrDict 

    json_repr = json.dumps(d) 
    return json.loads(json_repr, object_hook=_decode_dict) 

d = {u'status': {u'code': 0, u'pagesize': 10, u'version': u'1.0.0', u'msg': u'SuccessWithResult', u'total': 1, u'page': 1}, u'property': [{u'building': {u'summary': {u'bldgsNum': 1, u'unitsCount': u'0', u'archStyle': u'OLD', u'bldgType': u'SINGLE FAMILY', u'yearbuilteffective': 0, u'levels': 1, u'storyDesc': u'SINGLE FAMILY'}, u'construction': {u'roofcover': u'ASPHALT SHINGLE', u'wallType': u'WOOD SIDING', u'foundationtype': u'PIER', u'condition': u'FAIR'}, u'rooms': {u'bathstotal': 1.0, u'roomsTotal': 6, u'bathscalc': 1.0, u'bathfixtures': 0, u'bathsfull': 0, u'beds': 3, u'baths3qtr': 0, u'baths1qtr': 0, u'bathshalf': 0}, u'parking': {u'prkgType': u'DETACHED GARAGE', u'prkgSize': 0, u'garagetype': u'DETACHED GARAGE', u'prkgSpaces': u'0'}, u'interior': {u'fplctype': u'TYPE UNKNOWN', u'fplccount': 1, u'bsmtsize': 0, u'fplcind': u'Y'}, u'size': {u'universalsize': 1022, u'livingsize': 1022, u'sizeInd': u'LIVING SQFT ', u'grosssizeadjusted': 0, u'groundfloorsize': 1022, u'bldgsize': 1022, u'grosssize': 0}}, u'area': {u'taxcodearea': u'11', u'countrysecsubd': u'Bexar County', u'muncode': u'21', u'subdname': u'SOUTH PARK TERRACE BAITYS BL 3', u'countyuse1': u'A1', u'blockNum': u'11', u'munname': u'SAN ANTONIO'}, u'vintage': {u'lastModified': u'2017-9-23', u'pubDate': u'2017-10-12'}, u'utilities': {u'heatingtype': u'FORCED AIR', u'wallType': u'WOOD SIDING', u'coolingtype': u'AC.CENTRAL'}, u'summary': {u'proptype': u'SFR', u'propsubtype': u'SINGLE FAMILY', u'absenteeInd': u'SITUS FROM SALE (ABSENTEE)', u'propclass': u'Single Family Residence/Townhouse', u'yearbuilt': 1930, u'legal1': u'NCB 3130 BLK 11 LOT 35 AND 36', u'propIndicator': u'10', u'propLandUse': u'SFR'}, u'location': {u'distance': 0.0, u'elevation': 0.0, u'longitude': u'-98.484597', u'latitude': u'29.396664', u'geoid': u'CO48029,CS4893407,DB4838730,MT30003336,ND0000206694,ND0000567797,PL4865000,RS0000576252,SB000,SB000,SB000,ZI78210', u'accuracy': u'Street'}, u'lot': {u'lotnum': u'35', u'depth': 133, u'lotsize2': 5320, u'frontage': 40, u'lotsize1': 0.1221}, u'address': {u'matchCode': u'ExaStr', u'postal2': u'3873', u'postal3': u'C002', u'locality': u'San Antonio', u'country': u'US', u'countrySubd': u'TX', u'line2': u'SAN ANTONIO, TX 78210', u'line1': u'202 LORETTA PL', u'postal1': u'78210', u'oneLine': u'202 LORETTA PL, SAN ANTONIO, TX 78210'}, u'identifier': {u'apn': u'031300110350', u'apnOrig': u'03130-011-0350', u'fips': u'48029', u'obPropId': 12253857148029}}]} 

data = convert(d) 
city = data.property[0].address.locality 
print(city) # -> San Antonio 
zip_code = data.property[0].address.postal1 
print(zip_code) # -> 78210 
county = data.property[0].area.countrysecsubd 
print(county) # -> Bexar County 
# and so on and so forth... 
2

は、あなたがより少ない定型を書き込むことができますヘルパー関数を書く:

def follow(obj, path): 
    for seg in path.split(): 
      obj = obj[int(seg) if seg.isdigit() else seg] 
    return obj 

呼び出し:

prop = follow(data, "property 0") 
city = follow(prop, "address locality") 

など

+0

私はこの解決策を本当に気に入っていました。しかし、この場合は - d = {0: '0'、 '0': 'str 0'}、常に '0'を返します。 –

+1

はい、文字列の数値キーがないと想定しています。 '#0'のような実数のための特別な構文を追加することができます。 – kindall

1

など、独自の辞書のクラスの作成については何、

class DictQuery(dict): 
    def get(self, path, default = None): 
      keys = path.split("/") 
      val = None 

      for key in keys: 
       if val: 
        if isinstance(val, list): 
         val = [ v.get(key, default) if v else None for v in val] 
        else: 
         val = val.get(key, default) 
       else: 
        val = dict.get(self, key, default) 

       if not val: 
        break; 

      return val 

次に、それをそのように呼び出すことができます。

for row in csv: 
    print(DictQuery(row).get("property/address")) 

注:これはテストされておらず、試してみてください。

+0

それはなぜテストされていないのですか? – martineau

0
property = data['property'][0] 
city = property['address']['locality'] #etc. 
関連する問題