2

我一直试图从这里的其他帖子中弄清楚这一点,但做不到。

我有一本 Python 字典

old_dict = { (1,'a') : [2],
          (2,'b') : [3,4],
          (3,'x') : [5],
          (4,'y') : [5],
          (5,'b') : [3,4], 
          (5,'c') : [6],
          }

我需要扭转这一点,因此我将拥有:

new_dict = { (6,'c') : [5],
          (5,'x') : [3],
          (5,'y') : [4],
          (4,'b') : [5, 2],
          (3,'b') : [5, 2], 
          (2,'a') : [1],
          }

(这描述了有限状态机的边缘,我需要向后运行它:它必须像以前一样接受反向输入)

例如,在 old_dict 中,第一个键是 list (1, 'a') : [2],现在,这个应该变成(2, 'a'), [1]... 或(4,'y') : [5]变成(5,'y') : [4]等 - 我希望我的意思可以理解。

我一直在尝试用列表推导来解决这个问题,但还没有成功。

更新:我尝试了 FC的建议,但不知何故我无法让代码工作。我将它插入到一个函数中,如下所示:

old_dict1 = { (1,'a') : [2],
          (2,'b') : [3,4],
          (3,'x') : [5],
          (4,'y') : [5],
          (5,'b') : [3,4], 
          (5,'c') : [6],
          }

def reverse_dict(old_dict):
    new_dict = {}
    add_to_dict = new_dict.setdefault

    map(lambda kv: add_to_dict(kv[0], []).append(kv[1]),   
        sum([[((x, k[1]), k[0]) for x in v] for k, v in old_dict.items()],
            []))        # sum will take this to start adding
    return new_dict

new_dict1 = reverse_dict(old_dict1)

print(new_dict1)

但我只得到一个空字典{}

难道我做错了什么 ?(我对Python的了解真的很少,所以如果我犯了一个太愚蠢的错误,请原谅我......)

4

3 回答 3

8

这足够复杂,我不会为列表推导而烦恼。另外,我假设您不是在寻找任何严格顺序的值列表。

new_dict = {}
for k, vals in old_dict.items():
    k_num, k_char = k
    for num in vals:
        new_dict.setdefault((num, k_char), []).append(k_num)

或使用defaultdict

new_dict = collections.defaultdict(list)
for k, vals in old_dict.items():
    k_num, k_char = k
    for num in vals:
        new_dict[(num, k_char)].append(k_num)

对于那些对尽可能简洁感兴趣的人,我想到这个更压缩的版本也是一种选择。从可读性的角度来看,我不确定我对此有何看法,因此我更改了变量名称以更清晰:

new_dict = collections.defaultdict(list)
for (num_in, char_in), nums_out in old_dict.items():
    for num_out in nums_out:
        new_dict[(num_out, char_in)].append(num_in)
于 2012-06-01T22:11:07.577 回答
0

这适用于您的数据,把它当作一个丑陋的黑客只是为了好玩

最好用更多的代码行来做,这样更容易理解,但有时我无法抗拒写这个装置的诱惑。

希望能帮助到你。

def reverse_dict(old_dict):
    """
    >>> sorted(reverse_dict({(1,'a'): [2],
    ...               (2,'b'): [3,4],
    ...               (3,'x'): [5],
    ...               (4,'y'): [5],
    ...               (5,'b'): [3,4], 
    ...               (5,'c'): [6],
    ...              }).items())
    [((2, 'a'), [1]), ((3, 'b'), [2, 5]), ((4, 'b'), [2, 5]), ((5, 'x'), [3]), ((5, 'y'), [4]), ((6, 'c'), [5])]
    """
    new_dict = {}
    add_to_dict = new_dict.setdefault       # you could use a [defaultdict][1] instead

    map(lambda kv: add_to_dict(kv[0], []).append(kv[1]),   # if kv[0] not in dict get [] and add to it
        sum([[((x, k[1]), k[0]) for x in v] for k, v in old_dict.items()],
            []))        # sum will take this to start adding
    return new_dict

要测试代码,只需将其复制到一个文件so.py并像这样运行它:

$ python -m doctest so.py -v
Trying:
    sorted(reverse_dict({(1,'a'): [2],
                  (2,'b'): [3,4],
                  (3,'x'): [5],
                  (4,'y'): [5],
                  (5,'b'): [3,4], 
                  (5,'c'): [6],
                 }).items())
Expecting:
    [((2, 'a'), [1]), ((3, 'b'), [2, 5]), ((4, 'b'), [2, 5]), ((5, 'x'), [3]), ((5, 'y'), [4]), ((6, 'c'), [5])]
ok
1 items had no tests:
    so
1 items passed all tests:
   1 tests in so.reverse_dict
1 tests in 2 items.
1 passed and 0 failed.
Test passed.

它用于doctest更容易测试它是否在做你想做的事。

于 2012-06-01T22:51:38.140 回答
-1

我认为您对 a 的目的的理解存在问题dictdict不应将数据结构视为以任何特定方式排序,因为它使用哈希表来访问元素。您应该阅读文档,.items() 这里关于实现细节的注释也很重要。事实证明,实现可能会给你你似乎期望的顺序,但你不应该指望它。

如果顺序对您很重要,那么您应该list至少在代码中顺序很重要的部分使用 a。使用.items()你的方法dict来获取对的列表(key,value),然后你可以使用列表上的常用排序方法以任何你想要的方式对它们进行排序。

于 2012-06-02T05:27:15.757 回答