0

I have a multidictionary:

{'a': {'b': {'c': {'d': '2'}}},
 'b': {'b': {'c': {'d': '7'}}},
 'c': {'b': {'c': {'d': '3'}}},
 'f': {'d': {'c': {'d': '1'}}}}

How can I sort it based on the values '2' '3' '7' '1' so my output will be:

f.d.c.d.1
a.b.c.d.2
c.b.c.d.3
b.b.c.d.7
4

4 回答 4

3

You've got a fixed-shape structure, which is pretty simple to sort:

>>> d = {'a': {'b': {'c': {'d': '2'}}}, 'c': {'b': {'c': {'d': '3'}}}, 'b': {'b': {'c': {'d': '7'}}}, 'f': {'d': {'c': {'d': '1'}}}}
>>> sorted(d, key=lambda x: d[x].values()[0].values()[0].values()[0])
['f', 'a', 'c', 'b']
>>> sorted(d.items(), key=lambda x: x[1].values()[0].values()[0].values()[0])
[('f', {'d': {'c': {'d': '1'}}}),
 ('a', {'b': {'c': {'d': '2'}}}),
 ('c', {'b': {'c': {'d': '3'}}}),
 ('b', {'b': {'c': {'d': '7'}}})]

Yes, this is a bit ugly and clumsy, but only because your structure is inherently ugly and clumsy.

In fact, other than the fact that d['f'] has a key 'd' instead of 'b', it's even more straightforward. I suspect that may be a typo, in which case things are even easier:

>>> d = {'a': {'b': {'c': {'d': '2'}}}, 'c': {'b': {'c': {'d': '3'}}}, 'b': {'b': {'c': {'d': '7'}}}, 'f': {'b': {'c': {'d': '1'}}}}
>>> sorted(d.items(), key=lambda x:x[1]['b']['c']['d'])
[('f', {'b': {'c': {'d': '1'}}}),
 ('a', {'b': {'c': {'d': '2'}}}),
 ('c', {'b': {'c': {'d': '3'}}}),
 ('b', {'b': {'c': {'d': '7'}}})]

As others have pointed out, this is almost certainly not the right data structure for whatever it is you're trying to do. But, if it is, this is how to deal with it.

PS, it's confusing to call this a "multidictionary". That term usually means "dictionary with potentially multiple values per key" (a concept which in Python you'd probably implement as a defaultdict with list or set as its default). A single, single-valued dictionary that happens to contain dictionaries is better named a "nested dictionary".

于 2012-11-30T20:44:10.640 回答
2

在我看来,这种设计很难阅读和维护。您可以考虑用字符串名称替换内部字典吗?

例如:

mydict = {
    'a.b.c.d' : 2,
    'b.b.c.d' : 7,
    'c.b.c.d' : 3,
    'f.d.c.d' : 1,
}

这一个更容易排序并且更具可读性。

现在,字典由于其性质而无法分类。因此,您必须对它的例如列表表示进行排序:

my_sorted_dict_as_list = sorted(mydict.items(), 
                                key=lambda kv_pair: kv_pair[1])
于 2012-11-30T20:49:32.833 回答
1

你可以递归地做到这一点:

d = {'a': {'b': {'c': {'d': '2'}}}, 'c': {'b': {'c': {'d': '3'}}}, 'b': {'b': {'c': {'d': '7'}}}, 'f': {'d': {'c': {'d': '1'}}}}

def nested_to_string(item):

    if hasattr(item, 'items'):
        out = ''
        for key in item.keys():
            out += '%s.' % key + nested_to_string(item[key])
        return out
    else:
        return item + '\n'

print nested_to_string(d)

或者

def nested_to_string(item):
    def rec_fun(item, temp, res):
        if hasattr(item, 'items'):
            for key in item.keys():
                temp += '%s.' % key
                rec_fun(item[key], temp, res)
                temp = ''
        else:
            res.append(temp + item)

    res = []
    rec_fun(d, '', res)
    return res

你为什么要这样做。

于 2012-11-30T20:22:58.360 回答
1

你的数据结构基本上是一个多级树,所以做你想做的一个好方法是做所谓的深度优先遍历它,可以递归完成,然后稍微按摩中间结果进行排序并将它们格式化为所需的格式。

multidict = {'a': {'b': {'c': {'d': '2'}}},
             'b': {'b': {'c': {'d': '7'}}},
             'c': {'b': {'c': {'d': '3'}}},
             'f': {'d': {'c': {'d': '1'}}}}

def nested_dict_to_string(nested_dict):
    chains = []
    for key,value in nested_dict.items():
        chains.append([key] + visit(value))
    chains = ['.'.join(chain) for chain in sorted(chains, key=lambda chain: chain[-1])]
    return '\n'.join(chains)

def visit(node):
    result = []
    try:
        for key,value in node.items():
            result += [key] + visit(value)
    except AttributeError:
        result = [node]
    return result

print nested_dict_to_string(multidict)

输出:

f.d.c.d.1
a.b.c.d.2
c.b.c.d.3
b.b.c.d.7
于 2012-11-30T21:49:12.277 回答