0

给定嵌套列表:[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

它正在工作

称呼:

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 Starting 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。
    (第三个问题是我发布这个问题的主要问题)

编辑:

正如@tcaswell指出的那样:

你想怎么处理[1, {1: 2}]1应该映射到两者01根据您当前的规则。

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

4

3 回答 3

1

应该避免使用 isinstance()。那么还有其他方法可以编写此代码吗?

除了教科书练习外,我很少在数据中看到如此任意的异质性,因此我同意您isinstance尽可能避免的建议。所以一般的答案是:如果你发现自己在应对疯狂的结构,那么给你的代码设计得很糟糕,你应该修复它。换句话说,你调用的期望输出code(){(1, 2): 1, 1: 0, 3: 2, 4: 2, 5: 3, 6: 3}你能用那个不需要更多代码的值做些什么,至少像code()它本身一样无用复杂?

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

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

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

错误永远不应该悄无声息地过去。
除非明确沉默。

您永远不应该捕获您不知道如何处理的异常,并且打印错误消息很少被视为正确处理异常。我的一个旧答案更全面地解决了这个常见错误。

于 2013-09-24T16:18:39.930 回答
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 它是检测类型的唯一方法。

于 2013-09-24T16:42:31.620 回答
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()and type(),请阅读以下内容:

  1. python中isinstance()和type()的区别
  2. 检查 Python 变量类型的最佳(惯用)方法是什么?

虽然,这里提到的东西对你的问题并不适用,因为正如 msw 提到的,它看起来更像是一个教科书问题。除此之外,链接中的答案包含一些很好的建议。

缩短代码的基本规则是先把它写下来,又快又脏,然后看看你能用更短的代码片段代替什么来达到同样的效果。

于 2013-09-24T16:44:01.700 回答