将混合嵌套列表转换为线性字典

时间:2013-09-24 15:34:26

标签: python list dictionary tuples

给定嵌套列表:[1, (1, 2), [3, 4], {5: 6}],编写一个程序,将这些元素的元素作为键,并将这些元素的位置作为值。

我的代码:(阅读评论)

#!/usr/bin/python
def code(lst):
    '''
      lst: A nested hybrid list!
      type: list

      returns: linear dict
    '''
    d = {}
    try:
        for i, l in enumerate(lst):
            if isinstance(l, list): # I know lists are unhashable
                for e in l:
                    d[e] = i
            elif isinstance(l, dict): # I know dicts are unhashable
                for e in l.items():
                    d[e[0]] = i
                    d[e[1]] = i
            else:
                d[l] = i    
    except TypeError, e:
        print "invalid key!"
        print "Check your nested values"
    except Exception, e: # One should catch every possible exception else code fault
        printf "My Code fault!"
    return d

它是working

致电:

print code([1, (1, 2), {3: 4}, [5, 6]])

输出:

{(1, 2): 1, 1: 0, 3: 2, 4: 2, 5: 3, 6: 3}

我是Python学习者,我编写此代码时假设从列表中获取的密钥将是唯一的,例如: [1, 2, [1, 2]]是无效的输入。

[问题]

  1. 我只是想知道:我如何进一步改进我的代码,因此它变得很小而且速度快?
  2. 我从“Apress Beginning Python”中学习,应该避免使用isinstance()。那么有没有其他方法来编写这段代码?

  3. 您能否建议我如何改进任意嵌套和混合的代码,例如:

    #   0     1            2        3         <-- index
       [1, (1, 2), {3: [4, 5]}, [{6: 7} , 8]]
    

    输出:

      {1: 0, (1, 2): 1, 3: 2, 4: 2, 5: 2, 6: 3, 7: 3, 8: 3}  
     #    ^          ^     ^     ^     ^     ^     ^     ^ 
     #        index in outer list             
    

    我可以处理嵌套在两个级别,但嵌套在任何级别对​​我来说是不可能的,请提出一个技巧。一个建议就够了,但应该是Pythonic  (第3个问题是我发布这个问题的主要问题)

  4. 修改:

    如指出@tcaswell:

      

    您希望如何处理[1, {1: 2}]?根据您当前的规则,1应映射到01

    为简单起见,我假设此输入无效。 "assumption that key fetched from list will be unique"

3 个答案:

答案 0 :(得分:1)

  

应该避免使用isinstance()。那么有没有其他方法来编写这段代码?

除了教科书练习外,我很少看到数据的任意异构,因此我同意尽可能避免isinstance的建议。所以一般的答案是:如果你发现自己正在处理疯狂的结构,那么给你的代码设计很差,你应该解决这个问题。换句话说,您对code()的调用所需的输出是{(1, 2): 1, 1: 0, 3: 2, 4: 2, 5: 3, 6: 3}您可以对该值执行哪些操作,而不需要更多代码,至少与code()本身一样无用? / p>

要将此问题转换为C术语:您需要多长时间处理一组指向联合的指针?几乎从来没有,当你这样做时很痛苦,因为工会总是需要随身携带一个类型指示器,这样你才能确保访问正确的工会成员。

  

应该捕获每个可能的异常,否则代码错误

这是错的;您希望代码出错,因为它是查找错误的好方法。关注PEP-20

  

错误不应该默默地传递。
  除非明确地保持沉默。

您永远不应该捕获您不知道如何处理的异常,并且打印错误消息很少被视为正确处理异常。 old answer of mine addresses这个常见错误更充分。

答案 1 :(得分:1)

我无法理解你写的东西:

  

我写了这段代码,假设从列表中取出的密钥是唯一的,例如: [1, 2, [1, 2]]是无效的输入

然后您的“有效”输入是:

  

[1, (1, 2), {3: 4}, [5, 6]]

重复数字“1”......

无论如何要回答你的问题。我在if..else语句中写了一个递归方法(这应该解决任意嵌套项)和更多的“条目”。例如:

def foo(a):
    x = {}
    for i,b in enumerate(a):
        if isinstance(b,list):
            for k in b:
                x[k]=i
        elif isinstance(b,dict):
            for k in b.items():
                x[k[0]]=i
                x[k[1]]=i
        elif isinstance(b,set):
            for k in b:
                x[k]=i
        elif isinstance(b,tuple):
            for k in b:
                x[k]=i
        else:
            x[b]=i
    return x

foo([1,(2,3),{4,5},[6,7]])
{1: 0, 2: 1, 3: 1, 4: 2, 5: 2, 6: 3, 7: 3}

虽然我无法回答你关于isinstance功能有多快,但AFAIK却是检测类型的唯一方法。

答案 2 :(得分:1)

bigList = [1, (1, 2), {(3,9): [4, 5]}, [{6: 7} , 8]]
linear_dict = dict()

def nestedList(l, index = None, break_tuple = False):
    for count, item in enumerate(l):
        if type(item) is list:
            nestedList(item, index if index else count)
        elif type(item) is dict:
            nestedList(item.iteritems(), index if index else count, True)
        elif type(item) is tuple and break_tuple:
            nestedList(list(item), index)
        else:
            linear_dict[item] = index if index else count

nestedList(bigList)
print linear_dict

{(1, 2): 1, 1: 0, 4: 2, 5: 2, 6: 3, 7: 3, 8: 3, (3, 9): 2}

这更像是一个递归问题,而不是每个人说的列表,元组和字典。

关于isinstance()type(),请阅读以下内容:

  1. Differences between isinstance() and type() in python
  2. What is the best (idiomatic) way to check the type of a Python variable?
  3. 虽然,这里提到的事情并不适用于你的问题,因为正如msw所说,它似乎更像是一个教科书问题。除此之外,链接中的答案包含一些很好的建议。

    缩短代码的基本规则是首先将其写下来,快速而又脏,然后看看哪些可以用更短的代码片段来代替,它实现了相同的功能。