1

次のような(タプルなどの)リストのタプルのネストされたリストがあります。

[(' person', 
[(('surname', u'Doe', True),), 
(('name', u'John', False),), 
('contact', 
[(('email', u'john@doe.me', True),), 
(('phone', u'+0123456789', False),), 
(('fax', u'+0987654321', False),)]), 
('connection', 
[(('company', u'ibcn', True),), 
('contact', 
[(('email', u'mail@ibcn.com', True),), 
(('address', u'main street 0', False),), 
(('city', u'pythonville', False),), 
(('fax', u'+0987654321', False),)])])])]

リスト内の(double)タプルの数も、ネストの深さも知る方法はありません。

これを(辞書の)ネストされた辞書に変換して、次のようにブール値を削除したいと思います。

{'person': {'name': 'John', 'surname': 'Doe', 
    'contact': {'phone': '+0123456789', 'email': 'john@doe.me','fax': '+0987654321',
    'connection': {'company name': 'ibcn', 'contact':{'phone': '+2345678901',
                   'email': 'mail@ibcn.com', 'address': 'main street 0'
                   'city': 'pythonville', 'fax': +0987654321'
}}}}}

これまでのところ、ネストされた構造を行ごとに出力できる再帰的な方法しかありません。

def tuple2dict(_tuple):
    for item in _tuple:
        if type(item) == StringType or type(item) == UnicodeType:
            print item
        elif type(item) == BooleanType:
            pass
        else:
            tuple2dict(item)

しかし、私は正しい軌道に乗っているかどうかはわかりません...

編集:コンマが欠落していたため、元の構造を編集しました。

4

4 に答える 4

3

あなたは正しい方向に進んでいます。再帰的アプローチが機能します。サンプルデータからわかる限り、各タプルには最初にキーを含む文字列アイテムがあります。その後、値として別のタプルまたはリストを作成するか、文字列値の後にブール値のtrueまたはfalseを指定します。

編集:

再帰の秘訣は、いつ停止するかを知らなければならないということです。基本的に、あなたの場合、最も深い構造はネストされた3つのタプルであり、名前と値が一致しているように見えます。

少しハッキングします。私は恥ずかしそうに、これが世界で最も醜いコードであることを認めます。

def tuple2dict(data):
    d = {}
    for item in data:
        if len(item) == 1 and isinstance(item, tuple):
            # remove the nested structure, you may need a loop here
            item = item[0]
            key = item[0]
            value = item[1]
            d[key] = value
            continue
        key = item[0]
        value = item[1]
        if hasattr(value, '__getitem__'):
            value = tuple2dict(value)
        d[key] = value
    return d
于 2012-09-12T23:27:39.593 に答える
1

美しくはありません...しかしそれは機能します...基本的に

def t2d(t):
 if isinstance(t,basestring):return t
 length = len(t)
 if length == 1:
     return t2d(t[0])
 if length == 2:

     t1,t2 = t2d(t[0]),t2d(t[1])
     print "T:",t1,t2
     if isinstance(t1,dict) and len(t1) == 1:
         t2['name'] = t1.values()[0]
         t1 = t1.keys()[0]
     return dict([[t1,t2]])
 if length == 3 and isinstance(t[2],bool):
     return t2d(t[:2])

 L1 =[t2d(tp) for tp in t]
 L2 = [lx.items() for lx in L1]
 L3 = dict( [i[0] for i in L2])
 return L3

私はそれがあなたが投稿したdictで特に機能することを言及する必要があります...(会社が正しくセットアップされていなかったようですので、私はそれをハックしました(t2 ['name'] ...を参照))

于 2012-09-13T00:38:49.440 に答える
0

あなたは間違いなく正しい方向に進んでいます。再帰関数がその方法です。

辞書は、長さ2の反復可能なタプルから作成できます。これで、ブール値を取り除くために、スライスを使用できます。最初の2つの要素を除いてすべてを切り取ります。

 >> (1,2,3)[:3]
 (1,2)
于 2012-09-12T23:31:06.037 に答える
0

これが私の最終的な解決策です。あまりエレガントではありません、私は認めなければなりません。また、既存のキーと連結することにより、キーの複数のエントリを処理します。

def tuple2dict(_obj):
    _dict = {}
    for item in _obj:
        if isinstance(item, tuple) or isinstance(item, list):
            if isinstance(item[0], basestring):
                _dict[item[0]] = tuple2dict(item[1])
            else:
                if isinstance(item[0], tuple):
                    # if the key already exists, then concatenate the old
                    # value with the new one, adding a space in between.
                    _key = item[0][0]
                    if _key in _dict:
                        _dict[_key] = " ".join([_dict[_key], item[0][1]])
                    else:
                        _dict[_key] = item[0][1]
    return _dict
于 2012-09-13T11:37:33.293 に答える