2010-03-18 29 views
5
def flattenList(toFlatten): 
final=[] 
for el in toFlatten: 
    if isinstance(el, list): 
    final.extend(flattenList(el)) 
    else: 
    final.append(el) 
return final 

Khi tôi không biết danh sách sẽ tổ chức sâu đến mức nào, đây là cách duy nhất tôi có thể nghĩ để làm điều này.Có cách nào để thực hiện điều này không?

+0

Hãy thử sử dụng bốn dấu cách thay vì một dấu cách để thụt đầu dòng của bạn. Nó dễ đọc hơn và sẽ phù hợp với các nguyên tắc phong cách được sử dụng cho hầu hết các mã Python. (Hướng dẫn kiểu mã nhất Python phù hợp với là http://www.python.org/dev/peps/pep-0008/) –

+0

Các câu hỏi liên quan: "Danh sách các danh sách Flatten (một bất thường) trong Python" http: // stackoverflow .com/question/2158395/flatten-an-irregular-list-of-lists-in-python (liên kết đến các câu hỏi khác và câu trả lời hay) "Làm phẳng một danh sách nông trong python" http://stackoverflow.com/questions/406121 – jfs

Trả lời

2

Dưới đây là một tùy chọn (mặc dù có thể có một cái gì đó sạch hơn loại kiểm tra, như kiểm tra nếu có điều gì là iterable và do đó không phải là một "nguyên tử"):

def flatten(lst): 
    if not isinstance(lst,list): 
     return [lst] 
    else: 
     return reduce(lambda x,y:x+y,[flatten(x) for x in lst],[]) 

Nó dựa trên một cái gì đó đề án như thế nào.

+1

'try: return reduce (...); ngoại trừ TypeError: return [lst] ' – Debilski

+0

Điều đó hoàn hảo.Cảm ơn – Ishpeck

+0

@mitmatt, 1) Hàm' lambda x, y: x + y' được gọi là 'operator.add'. 2) Thuật toán của bạn là không cần thiết O (n * m) ish, khi thuật toán tuyến tính rõ ràng hơn. –

7
  1. Bạn nên tránh đánh máy bằng Python. Trong trường hợp này, điều này có nghĩa là tránh các cấu trúc tùy ý lồng nhau nơi bạn phân biệt theo loại. Bạn có thể xây dựng loại nút của riêng mình mà bạn có thể duyệt qua bằng các phương pháp khác so với kiểu gõ, như nhìn vào một thuộc tính cụ thể.

  2. Để làm phẳng một cấp hoặc chính xác n, hãy xem itertools.chain.from_iterable.

  3. Tôi không biết ý bạn là gì bởi "chức năng". Mã này là khá chức năng: nó sử dụng đệ quy (không phải tín dụng của nó!) Và nó không làm thay đổi đối số của nó. (Nói đúng ra, nó sử dụng nhà nước có thể thay đổi để xây dựng một danh sách, nhưng đó chỉ là cách bạn làm điều đó trong Python.

  4. Tôi cho rằng một thuộc tính chức năng hơn sẽ đánh giá lười biếng. Bạn có thể thực hiện điều này thusly

    def flatten(toFlatten): 
        for item in toFlatten: 
         if isinstance(item, list): # Ewww, typchecking 
          for subitem in flatten(item): # they are considering adding 
           yield subitem    # "yield from" to the language 
                  # to give this pattern syntax 
         else: 
          yield item 
    
  5. Việc đệ quy rất hạn chế trong Python (ít nhất, trong tất cả các triển khai chính của nó) và nói chung nên tránh cho độ sâu tùy ý, có thể viết lại (và tất cả mã đệ quy) để sử dụng lặp lại. nhiều khả năng mở rộng hơn (và ít chức năng hơn, đó là một điều tốt trong Python, mà không phải là đặc biệt thích hợp cho FP.)

+0

@Mike Graham: Tôi muốn có thể vượt qua trong danh sách chứa danh sách chứa danh sách, chứa danh sách, v.v., và san bằng tất cả các con đường xuống một đĩa đơn kết quả. Tôi muốn: [1,2, [3,4,5,6], 7,8, [9,10, [11,12, [13, [14,15], 16], 17], 20 ]] Để xuất hiện dưới dạng: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20] Nếu tôi biết trước danh sách lồng nhau sâu bao nhiêu, điều này sẽ đủ: def mergeLists (seq): \t trả về giảm (lambda x, y: x + y, seq) – Ishpeck

+0

1) Ngừng muốn điều đó. Xác định cấu trúc của bạn khác nhau. 2) Chiến lược 'reduce' của bạn là phép nhân trong thứ tự lớn-O; các thuật toán tuyến tính là hiển nhiên. –

+0

Câu trả lời chung chung hơn: http://stackoverflow.com/questions/2158395/flatten-an-irregular-list-of-lists-in-python/2158532#2158532 – jfs

2

Dưới doc cho itertools, có một chức năng flatten()

+0

Không có trên trang đó. –

+1

@Andrew Aylett, Đây là một công thức, không phải trong chính mô-đun. Đó là trên trang đó. –

+0

@Mike: Thừa nhận nó, bạn đã chỉnh sửa tài liệu sau khi tôi đăng bình luận của mình. Không chắc chắn làm thế nào tôi bỏ lỡ điều đó - nó đã không xuất hiện khi tôi tìm kiếm trang tại nơi làm việc: P. –

3

Câu trả lời này giải thích tại sao bạn không muốn sử dụng reduce cho điều này trong Python.

Hãy xem xét đoạn

reduce(operator.add, [[1], [2], [3], [4], [5]]) 

gì thực hiện điều này phải làm gì?

[1] + [2] => [1, 2] 
[1, 2] + [3] => This makes a new list, having to go over 1, then 2, then 3. [1, 2, 3] 
[1, 2, 3] + [4] => This has to copy the 1, 2, and 3 and then put 4 in the new list 
[1, 2, 3, 4] + [5] => The length of stuff I have to copy gets bigger each time! 

Hành vi bậc hai này hoàn toàn tránh được: giải pháp gốc (và bất kỳ giải pháp nào khác) không tạo thành các bước sao chép trung gian này.

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