给定嵌套列表:[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]]
是无效的输入。
[问题]
我从“Apress Beginning Python”中学习,应该避免使用isinstance()
。那么有没有其他方法来编写这段代码?
您能否建议我如何改进任意嵌套和混合的代码,例如:
# 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个问题是我发布这个问题的主要问题)
修改:
如指出@tcaswell:
您希望如何处理
[1, {1: 2}]
?根据您当前的规则,1
应映射到0
和1
。
为简单起见,我假设此输入无效。 "assumption that key fetched from list will be unique"
答案 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()
,请阅读以下内容:
虽然,这里提到的事情并不适用于你的问题,因为正如msw所说,它似乎更像是一个教科书问题。除此之外,链接中的答案包含一些很好的建议。
缩短代码的基本规则是首先将其写下来,快速而又脏,然后看看哪些可以用更短的代码片段来代替,它实现了相同的功能。