Как разделить список на n равных частей, python - PullRequest
11 голосов
/ 07 ноября 2010

Приведенный ( любой ) список слов lst Я должен разделить его на 10 равных частей.

x = len(lst)/10

как дать этим частям имена переменных?

В выводе мне нужно 10 переменных (part1, part2... part10) с x количеством слов в нем.

Ответы [ 7 ]

29 голосов
/ 07 ноября 2010

Однострочник возвращает список списков, учитывая список и размер куска:

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

Тестирование:

>>> 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]]

Обновление:

* 1009Я думаю, что вопрос, который действительно задают, это функция, которая, учитывая список и число, возвращает список, содержащий списки $ (число), с равномерно распределенными элементами исходного списка.Таким образом, ваш пример lol (x, 7) должен действительно возвращать [[20,21,22], [23,24,25], [26,27], [28,29], [30,31], [32], 33], [34,35]].- markrian

В данном случае вы можете попробовать:

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

Я уверен, что это можно улучшить, но мне лень.: -)

>>> slice_list(x, 7)
[[20, 21, 22], [23, 24, 25], 
 [26, 27], [28, 29], 
 [30, 31], [32, 33], 
 [34, 35]]
2 голосов
/ 07 ноября 2010

См. этот вопрос о том, как генерировать равные порции списка.Затем, если вы действительно нуждаетесь в них в отдельных переменных, вы можете сделать:

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

Но я бы порекомендовал сделать код более общим, а не жестко кодировать его из 10 частей.

1 голос
/ 09 марта 2018

Чтобы достичь того же результата, что и при обновлении Пауло (разделить список на n кусков, размер которых отличается только на 1), ниже приведено элегантное решение с использованием рекурсии.

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

Пример:

lst = list(range(13))
print divide(lst,5) # [[0, 1], [2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
1 голос
/ 12 августа 2016

Если вам не нужно применять смежные части выходных элементов, то следующий простой фрагмент сделает эту работу:

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)
    ]

В основном код группирует элементы на основе остатков по модулю. И именно поэтому элементы в списке вывода не будут смежными. Например, если введено значение range(21) вместо

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

вы бы получили

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

Надеюсь, это поможет.

1 голос
/ 07 ноября 2010

Я напишу этот код, чтобы вы изучили технику, но вы не должны этого делать.Суть типов данных контейнера, таких как list и set, заключается в том, что вы можете иметь произвольное содержимое без необходимости создавать переменные для каждого элемента.Итак,

Не делайте этого

>>> 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]

(рецепт chunks взят из ответа Неда Батчелдера в связанном вопросе. Причина, по которой вы не должныЭто означает, что изменение locals (или даже globals или vars) не является хорошей практикой: оно вызывает трудно определяемое поведение и, возможно, очень неприятные ошибки.

0 голосов
/ 19 июня 2016

Видел несколько решений, но не мог опубликовать мое:

# 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)

Конечно, можно подвести итог, конечно, но я думаю, что так будет понятно.

0 голосов
/ 07 ноября 2010

Использование кортежа / списка результатов - самый разумный подход

Если вам нужно определить новые переменные, вы можете

  1. используйте setattr и добавляйте новые атрибуты к любому object. Это безопасно, поскольку вы не будете перезаписывать существующие переменные:
    res = object()
    ...
    setattr(res, "part"+index, part_generated)
    
  2. добавляет сгенерированные переменные в словарь locals() или globals() в зависимости от контекста, в котором работает ваш код.
...