递归地将列表列表爆炸到"原子列表"

时间:2014-06-19 21:24:33

标签: python json list geojson

我遇到python中嵌套列表的困难(这是geojson坐标的结构)

这是一个例子

更新示例以避免混淆

DictofCoordinates = {
'a': [1,1],
'b': [[2, 2], [2,2], [2, 2]],
'c': [[[3,3], [3, 3], [3, 3]]],
'd': [[[41, 41], [41, 41]], 
  [[42, 42], [42, 42]]]
 }

我想得到的是除了(坐标)对之外不包含任何其他内容的列表。这就是我所说的“列表的原子列表”(因为没有更好的术语)

所以

 - for a : the list  [1, 1]
 - for b : [[2, 2], [2,2], [2, 2]]
 - for c : [[3,3], [3, 3], [3, 3]]
 - for d : the two lists [[41, 41], [41, 41]] and  [[42, 42], [42, 42]]]

here获取灵感,这是我尝试过的

def ExplodeTolist(xList):
for x1 in xList:
    if isinstance(x1[0], (float, int, long)):
        yield x1
    else:
        for x2 in ExplodeTolist(x1):
            yield x2 

但它不起作用

for x in ExplodeTolist(DictofCoordinates.values()):
   print x        

任何帮助表示赞赏。谢谢

3 个答案:

答案 0 :(得分:2)

如果我理解正确,您只想处理每个列表的内容,如果它包含更多列表。否则,您想要返回列表本身。我认为你所犯的最大错误就是你的函数是递归的,所以它尽可能地深入,你最终得到的只是一个迭代器。试试这个:

# You might want to modify this method to
# return False if it passes isinstance(x, basestring)
def is_iterable(x):
    try:
        iter(x)
        return True
    except TypeError:
        return False

def get_elements(coordinate_dict):
    for v in coordinate_dict.values():
        if is_iterable(v[0]):
            for i in v:
                yield i
        else:
            yield v

当它找到可迭代的内容时,它会遍历列表并返回元素。如果列表的内容可迭代,则只返回列表。关键的区别在于,当它找到可迭代的内容时,它只迭代一层

正如评论中所见,关于如何测试某些内容是否可迭代存在争议。我建议您查看In Python, how do I determine if an object is iterable?及其答案,以便对该主题进行更多讨论。

这是输出。它有点乱序,因为dict是无序的,但所有元素都在那里:

>>> for i in get_elements(d):
...      print i
...
[1, 1]
[[3, 3], [3, 3], [3, 3]]
[2, 2]
[2, 2]
[2, 2]
[[41, 41], [41, 41]]
[[42, 42], [42, 42]]

答案 1 :(得分:1)

实际上你只需要检查element [0]是否是一个列表。

def flatten(items):
    for elem in items:
        if isinstance(elem[0],list):
            for sub_elem in elem:
                yield sub_elem
        else:
            yield elem

print list(flatten(DictofCoordinates.values())) 
[[1, 1], [[3, 3], [3, 3], [3, 3]], [2, 2], [2, 2], [2, 2], [[41, 41], [41, 41]], [[42, 42], [42, 42]]]

匹配您的新输出:

def flatten(items):
    for elem in items:
        if sum(isinstance(i, list) for i in elem) == 0 or sum(isinstance(i, list) for i in elem[0]) == 0:
            yield elem
        else:
            for sub_elem in elem:
                yield sub_elem

print (list(flatten(DictofCoordinates.values())))
[[1, 1], [[3, 3], [3, 3], [3, 3]], [[2, 2], [2, 2], [2, 2]], [[41, 41], [41, 41]], [[42, 42], [42, 42]]]

答案 2 :(得分:0)

此函数将返回您描述的原子。

def getAtoms(lst):
    for l in lst:
        yield l