2010-11-07 29 views
11

thể trùng lặp:
How do you split a list into evenly sized chunks in Python?làm thế nào để phân chia danh sách thành n phần bằng nhau, trăn

Given (bất kỳ) danh sách các từ lst tôi nên chia thành 10 phần bằng nhau .

x = len(lst)/10 

cách đặt tên cho các phần này?

Trong đầu ra, tôi cần 10 biến (part1, part2... part10) với x số từ trong đó.

bất kỳ ý tưởng nào?

+1

Bạn không đưa ra tên các bộ phận. Bạn trả về một danh sách các danh sách. – delnan

+0

Cách tách? '[1,2,3,4,5, ... 100]' trở thành '[1,2,3, ...], [11,12,13, ...], ...' hoặc ' [1,11,21, ...], [2,12,22, ...], ... 'hoặc ngẫu nhiên hay cái gì? – kennytm

+0

Tại sao không phải một danh sách hoặc danh sách khác, danh sách này sẽ chứa các danh sách phụ? Và sau đó tham khảo bằng cách sử dụng vị trí? Nó sẽ năng động hơn sau đó sử dụng các biến.

 res = divide_list(l, 10) print res[0] 
khachik

Trả lời

2

Xem this question để biết cách tạo các phần bằng nhau của danh sách. Sau đó, nếu bạn thực sự cần chúng trong các biến riêng biệt, bạn có thể thực hiện:

part1, part2, ..., part10 = (part for part in chunks(lst, len(lst)/10)) 

Nhưng tôi khuyên bạn nên tạo mã chung hơn, thay vì viết mã cứng thành 10 phần.

1

Tôi sẽ viết mã này để bạn tìm hiểu kỹ thuật, nhưng bạn không nên làm điều này. Điểm của các kiểu dữ liệu vùng chứa như listset là bạn có thể có nội dung tùy ý mà không phải tạo biến cho từng phần tử. Vì vậy,

Đừng làm

>>> def chunks(l, n): 
...  for i in xrange(0, len(l), n): 
...   yield l[i:i+n] 
... 
>>> for i, chunk in enumerate(chunks(range(100), 10)): 
...  locals()["part{0}".format(i)] = chunk 
... 
>>> part0 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> part1 
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 
>>> part2 
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29] 

(Công thức chunks này là từ Ned Batchelder's answer trong câu hỏi liên quan. Lý do bạn không nên làm điều này là sửa đổi locals (hoặc thực sự globals hoặc vars) là không thực hành tốt: nó gây ra khó xác định hành vi và lỗi có thể rất khó chịu

+1

'khối' không chia l thành n phần, nó chia l thành' len (l)/n + 1' phần nếu 'len (l)% n! = 0' hoặc' len (l)/n' phần nếu 'len (l)% n == 0'. – khachik

28

One-liner trả về một danh sách liệt kê, được đưa ra một danh sách và kích thước đoạn:.

>>> lol = lambda lst, sz: [lst[i:i+sz] for i in range(0, len(lst), sz)] 

Thử nghiệm:

>>> x = range(20, 36) 
>>> print x 
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35] 

>>> lol(x, 4) 
[[20, 21, 22, 23], 
[24, 25, 26, 27], 
[28, 29, 30, 31], 
[32, 33, 34, 35]] 

>>> lol(x, 7) 
[[20, 21, 22, 23, 24, 25, 26], 
[27, 28, 29, 30, 31, 32, 33], 
[34, 35]] 

Cập nhật:

Tôi nghĩ câu hỏi thực sự là yêu cầu là một chức năng mà, được đưa ra một danh sách và một số, trả về một danh sách có chứa $ danh sách (số), với các mục trong danh sách gốc được phân phối đồng đều. Vì vậy, ví dụ về lol (x, 7) của bạn thực sự phải trả về [[20,21,22], [23,24,25], [26,27], [28,29], [30,31], [32 , 33], [34,35]]. - markrian

Vâng, trong trường hợp này, bạn có thể thử:

def slice_list(input, size): 
    input_size = len(input) 
    slice_size = input_size/size 
    remain = input_size % size 
    result = [] 
    iterator = iter(input) 
    for i in range(size): 
     result.append([]) 
     for j in range(slice_size): 
      result[i].append(iterator.next()) 
     if remain: 
      result[i].append(iterator.next()) 
      remain -= 1 
    return result 

tôi chắc chắn rằng điều này có thể được cải thiện nhưng tôi cảm thấy lười biếng.:-)

>>> slice_list(x, 7) 
[[20, 21, 22], [23, 24, 25], 
[26, 27], [28, 29], 
[30, 31], [32, 33], 
[34, 35]] 
+1

Tôi nghĩ câu hỏi thực sự hỏi là một hàm, được đưa ra một danh sách và một số, trả về một danh sách chứa các danh sách $ (số), với các mục của danh sách gốc được phân phối đồng đều. – markrian

+0

Vì vậy, ví dụ về lol (x, 7) của bạn thực sự phải trả về [[20,21,22], [23,24,25], [26,27], [28,29], [30,31], [ 32,33], [34,35]]. – markrian

+0

@markrian: tâm trí bạn, rất nhiều người hiểu lầm câu hỏi, đó là một chỉ báo về chất lượng của nó - nhưng bạn có thể đúng, xem cập nhật của tôi. –

0

Sử dụng tuple/liệt kê kết quả một - cách tiếp cận hợp lý nhất

Nếu bạn cần xác định biến mới, bạn có thể

  1. sử dụng setattr và thêm thuộc tính mới cho bất kỳ object . Nó là an toàn vì bạn sẽ không ghi đè lên các biến hiện có:.
     
    res = object() 
    ... 
    setattr(res, "part"+index, part_generated) 
    
  2. add tạo biến để locals() hoặc globals() từ điển tùy thuộc vào bối cảnh mã của bạn đang chạy trong
0

Nhìn một số giải pháp, nhưng không thể giúp bài đăng của tôi:

# List 
lst = range(103) 

# number of slices 
nSlices = 10 

# splitted list 
slices = [len(lst) // (nSlices)] * nSlices 

# but points are still missing! 
remainder = len(lst)-sum(slices) 

# split missing points across slices 
slices[:remainder] = [ii + 1 for ii in slices[:remainder]] 

splittedList = [lst[sum(slices[:ii]):sum(slices[:ii+1])] for ii in    range(nSlices)] 
print lst 
print '\n'.join("{}".format(n) for n in splittedList) 

Có thể tóm tắt thêm, tất nhiên, nhưng tôi nghĩ cách này rõ ràng để đọc.

1

Nếu bạn không cần phải thực thi phần tiếp giáp của các yếu tố đầu ra, sau đó đoạn đơn giản sau đây sẽ thực hiện công việc:

def even_divide(lst, num_piece=4): 
    return [ 
     [lst[i] for i in range(len(lst)) if (i % num_piece) == r] 
     for r in range(num_piece) 
    ] 

yếu tố cơ bản mã được nhóm dựa trên modulo dư lượng. Và vì chính xác điều đó, các phần tử trong danh sách đầu ra sẽ không tiếp giáp. Ví dụ, nếu đầu vào là range(21), thay vì

[[0, 1, 2, 3, 4, 5],[6, 7, 8, 9, 10],[11, 12, 13, 14, 15],[16, 17, 18, 19, 20]] 

bạn sẽ nhận được

[[0, 4, 8, 12, 16, 20],[1, 5, 9, 13, 17],[2, 6, 10, 14, 18],[3, 7, 11, 15, 19]] 

Hy vọng nó giúp.

0

Để đạt được kết quả tương tự như cập nhật của Paulo (chia danh sách thành các khối có kích thước chỉ khác 1), sau đây là giải pháp thanh lịch khi sử dụng đệ quy.

def divide(lst, n): 
    p = len(lst) // n 
    if len(lst)-p > 0: 
     return [lst[:p]] + divide(lst[p:], n-1) 
    else: 
     return [lst] 

Ví dụ:

lst = list(range(13)) 
print divide(lst,5) # [[0, 1], [2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]] 
Các vấn đề liên quan