2013-02-08 41 views
5

Tôi đang đệ quy thông qua tệp xml, sử dụng etree.Python: tránh vòng lặp lồng nhau trên mảng

import xml.etree.ElementTree as etree 
tree = etree.parse('x.xml') 
root = tree.getroot() 
for child in root[0]: 
for child in child.getchildren(): 
     for child in child.getchildren(): 
      for child in child.getchildren(): 
       print(child.attrib) 

cách thức thành ngữ trong python để tránh những vòng lặp lồng nhau này là gì.

getchildren() ⇒ list of Element instances [#] 
    Returns all subelements. The elements are returned in document order. 

Returns: 
A list of subelements. 

tôi thấy một số bài trong SO như, Avoiding nested for loops nhưng không dịch trực tiếp đến việc sử dụng của tôi.

cảm ơn.

+1

'itertools.product' là một cách hay để tránh các vòng lồng nhau. Tại sao điều đó không giúp bạn sử dụng? –

+0

Bạn có đặc biệt muốn các thuộc tính cho các phần tử 4 con sâu? – bogatron

+0

xin lỗi, tôi không có nghĩa là itertools.product không phù hợp với tôi, nhưng không thể dịch ví dụ đó thành các mảng như trong trường hợp của tôi. Tôi không thực hiện nhiều Python, nhưng sẽ cố gắng. – bsr

Trả lời

3

Nếu bạn muốn nhận được những đứa trẻ mà n mức sâu trong cây, và sau đó lặp qua chúng, bạn có thể làm:

def childrenAtLevel(tree, n): 
    if n == 1: 
     for child in tree.getchildren(): 
      yield child 
    else: 
     for child in tree.getchildren(): 
      for e in childrenAtLevel(child, n-1): 
       yield e 

Sau đó, để có được những yếu tố bốn cấp độ sâu, bạn sẽ đơn giản nói:

for e in childrenAtLevel(root, 4): 
    # do something with e 

Hoặc, nếu bạn muốn để có được tất cả các nút lá (tức là các nút mà không có bất kỳ con mình), bạn có thể làm:

def getLeafNodes(tree): 
    if len(tree) == 0: 
     yield tree 
    else: 
     for child in tree.getchildren(): 
      for leaf in getLeafNodes(child): 
       yield leaf 
2

itertools.chain.from_iterable sẽ làm phẳng một cấp làm tổ; bạn có thể sử dụng functools.reduce để áp dụng nó n lần (Compressing "n"-time object member call):

from itertools import chain 
from functools import reduce 

for child in reduce(lambda x, _: chain.from_iterable(x), range(3), root): 
    print(child.attrib) 

Lưu ý rằng getchildren là bị phản đối; việc lặp lại một nút sẽ sinh con của nó trực tiếp.

Các vấn đề liên quan