2012-04-12 60 views
12

Thông thường, bạn muốn đi theo một cách khác xung quanh, like here. Tôi đã tự hỏi làm thế nào bạn có thể chuyển đổi một danh sách phẳng vào một danh sách của danh sách, quasy mảng định hình lại trong pythonchuyển đổi danh sách phẳng thành danh sách trong python

Trong NumPy bạn có thể làm một cái gì đó như:

>>> a=numpy.aranage(9) 
>>> a.reshape(3,3) 
>>> a 
array([[0, 1, 2], 
    [3, 4, 5], 
    [6, 7, 8]]) 

tôi đã tự hỏi làm thế nào bạn làm ngược lại, và giải pháp thông thường của tôi là:

>>> Mylist 
['a', 'b', 'c', 'd', 'e', 'f'] 
>>> newList = [] 
for i in range(0,len(Mylist),2): 
...  newList.append(Mylist[i], Mylist[i+1]) 
>>> newList 
[['a', 'b'], ['c', 'd'], ['e', 'f']] 

có cách nào "Pythonic" hơn để làm điều đó không?

+0

tốt nhất là không sử dụng 'danh sách' làm tên biến vì có hàm dựng sẵn' list() ' – jamylak

+0

yeap bạn đúng, tôi chỉ chỉnh sửa mã nhanh, mã ban đầu của tôi không giống như vậy. – Oz123

Trả lời

27
>>> l = ['a', 'b', 'c', 'd', 'e', 'f'] 
>>> zip(*[iter(l)]*2) 
[('a', 'b'), ('c', 'd'), ('e', 'f')] 

Vì nó đã được chỉ ra bởi @Lattyware, điều này chỉ hoạt động nếu có đủ các mục trong mỗi đối số đến zip chức năng mỗi lần nó trả về một tuple. Nếu một trong các tham số có ít mục hơn các mục khác, các mục sẽ bị cắt bỏ ví dụ.

>>> l = ['a', 'b', 'c', 'd', 'e', 'f','g'] 
>>> zip(*[iter(l)]*2) 
[('a', 'b'), ('c', 'd'), ('e', 'f')] 

Nếu đây là trường hợp sau đó nó là tốt nhất để sử dụng giải pháp của @Sven Marnach

How does zip(*[iter(s)]*n) work

+3

Giải pháp này chỉ hoạt động nếu có đủ các mục để điền vào, nếu không các mục sẽ bị cắt. –

+0

Tạo trình tạo sau đó sao chép tham chiếu đến nó; tài giỏi. –

+1

@NickT về mặt kỹ thuật nó là một trình lặp không phải là máy phát điện và tôi không thể lấy tín dụng cho sự thông minh :) – jamylak

11

này thường được thực hiện bằng cách sử dụng công thức mú từ itertools documentation:

def grouper(n, iterable, fillvalue=None): 
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" 
    args = [iter(iterable)] * n 
    return itertools.izip_longest(fillvalue=fillvalue, *args) 

Ví dụ:

>>> my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] 
>>> list(grouper(2, my_list)) 
[('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', None)] 
0

Nếu một thích một danh sách liệt kê, chứ không phải là một danh sách các hàng từ một danh sách bằng phẳng, sau đó người ta có thể làm điều này:

a = range(20) # sample starting list 
    b = [] # new list 
    c = [] # alternate new list 
    # ny is length of new list. nx length of each list within it 
    nx = 5; ny = 4 
    bb = 0; ee = bb + nx # option one: sliding indeces for slices. 
    for ii in range(ny-1): 
     bb += nx 
     ee += nx 
     b.append(a[bb:ee]) 
     c.append(a[slice(ii*nx,nx*(ii+1))]) # option two, use slice() 

(Tôi đã chơi xung quanh với thu hẹp toàn bộ vòng lặp for thành một dòng với tính năng hiểu danh sách, nhưng chưa thành công. cách mà tôi đã sử dụng nó, slice() gần như có thể giúp bạn ở đó.) Một lợi thế có thể có của những cách tiếp cận này so với những người khác được đề cập là nếu danh sách căn hộ ban đầu của bạn không phải là một loạt các kích thước mới, mong muốn của bạn danh sách các danh sách, bạn sẽ không mất bất kỳ dữ liệu nào. Thông báo trước là danh sách cuối cùng sẽ ngắn hơn tất cả những người khác, vì nó sẽ chứa các "thức ăn thừa". được chấp thuận, không phải những phương pháp nào cũng tấn công tôi như rất nhiệt tình.

+0

Tôi không hiểu tại sao bạn đang sử dụng 'slice()' trong phương pháp thứ hai, chứ không phải là cú pháp slice. Việc tính toán không có nghĩa là bạn không thể sử dụng 'a [ii * nx: nx * (ii + 1)]' hoặc bất kỳ điều gì. – Blckknght

5

Một cách khác để tạo ra một danh sách liệt kê có thể được đơn giản hóa như hình dưới đây:

>>>MyList = ['a','b','c','d','e','f'] 
# Calculate desired row/col 
>>>row = 3 
>>>col = 2 
>>>NewList = [MyList[col*i : col*(i+1)] for i in range(row)] 
>>>NewList 
[['a', 'b', 'c'], ['d', 'e', 'f']] 

này có thể phương pháp có thể được mở rộng để tạo ra bất kỳ hàng và cột kích thước. Nếu bạn chọn giá trị hàng và cột sao cho row*col >len(MyList), danh sách con (hàng) chứa giá trị cuối cùng trong MyList sẽ kết thúc ở đó và NewList sẽ được điền đầy đủ số danh sách trống phù hợp để đáp ứng thông số hàng/col

>>>MyList = ['a','b','c','d','e','f','g','h'] 
>>>row = 3 
>>>col = 3 
>>>NewList = [MyList[col*i : col*(i+1)] for i in range(row)] 
>>>NewList 
[['a', 'b', 'c'], ['d', 'e', 'f'], ['g','h']] 

>>>row = 4 
>>>col = 4 
>>>NewList = [MyList[col*i : col*(i+1)] for i in range(row)] 
[['a', 'b', 'c', 'd'], ['e', 'f', 'g','h'], [], []] 
+1

Tôi đoán rằng đó phải là câu trả lời được chấp nhận vì câu hỏi đã yêu cầu một danh sách các danh sách chứ không phải danh sách các bộ dữ liệu. Hoặc câu trả lời của Robert trong bình luận ở trên. –

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