Разделить список на несколько списков на основе индексов [duplicate]

Вы также можете посмотреть верхнюю часть оболочки MySQL при первом входе в систему. Фактически она показывает версию.

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 67971
Server version: 5.1.73 Source distribution

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
49
задан drjeep 3 August 2009 в 13:31
поделиться

9 ответов

Это самое простое и самое питоническое решение, о котором я могу думать:

def partition(alist, indices):
    return [alist[i:j] for i, j in zip([0]+indices, indices+[None])]

, если входы очень большие, тогда решение итераторов должно быть более удобным:

from itertools import izip, chain
def partition(alist, indices):
    pairs = izip(chain([0], indices), chain(indices, [None]))
    return (alist[i:j] for i, j in pairs)

и, конечно же, очень, очень ленивое решение для парней (если вы не возражаете получать массивы вместо списков, но в любом случае вы всегда можете вернуть их в списки):

import numpy
partition = numpy.split
47
ответ дан fortran 21 August 2018 в 01:00
поделиться
  • 1
    Тот -1 отключит последний элемент. Вы можете использовать None вместо того, чтобы обрабатываться так же, как и пустая часть среза (также для начала, хотя там это не имеет значения) – Brian 29 July 2009 в 10:21
  • 2
    да, вы правы ... Моя первоначальная версия имела len (alist), и она работала нормально, но я заменил на -1, поскольку это показалось менее подробным: -s – fortran 29 July 2009 в 10:23
  • 3
    изменил его на None :-) – fortran 29 July 2009 в 10:25
  • 4
    @Brian Вау, мне просто нужно отрезать последний элемент! Благодаря! – Sibbs Gambling 5 September 2013 в 09:05
  • 5
    раздел является вводящим в заблуждение именем, так как на многих языках функция раздела разбивает список на два списка - передачи элементов и элементов, не соответствующих критериям (которые передаются как функция A-& gt; Boolean), например. (даже, [1, 2, 3, 4, 5]) = ([2, 4], [1, 3, 5]) – Velizar Hristov 18 November 2015 в 14:36

Множество индексов - это индексы. Переход к простоте / удобочитаемости.

indices = [5, 12, 17]
input = range(20)
output = []

for i in reversed(indices):
    output.append(input[i:])
    input[i:] = []
output.append(input)

while len(output):
    print output.pop()
2
ответ дан anthony 21 August 2018 в 01:00
поделиться
  • 1
    & Quot; индексы & Quot; и "индексы" оба правильны. & Quot; индексы & Quot; представляет собой плюрализацию "индекса" и более распространен в США, тогда как "индексы" происходит от латыни и чаще встречается в Великобритании. – Blixt 29 July 2009 в 08:45
  • 2
    Нет, "индексы" также является совершенно правильным словом. – Glenn Maynard 29 July 2009 в 08:46
  • 3
    Кто-нибудь хотел обсудить жизнеспособность работы справа налево? или это GrammarOverflow сейчас? – anthony 29 July 2009 в 08:52
  • 4
    Рабочее право налево предполагает, что вы либо вставляете в другие места, либо в конец, или переверните список перед его возвратом. Любой случай менее идеален. – Cide 29 July 2009 в 08:58
  • 5
    -1 Он мутирует вход ... aarrgghh !! – John Machin 29 July 2009 в 14:16

Мое решение похоже на Il-Bhima.

>>> def parts(list_, indices):
...     indices = [0]+indices+[len(list_)]
...     return [list_[v:indices[k+1]] for k, v in enumerate(indices[:-1])]

Альтернативный подход

Если вы хотите немного изменить способ ввода индексов, от абсолютных индексов до относительных (т. е. от [5, 12, 17] до [5, 7, 5], ниже также вы получите желаемый результат, в то время как он не создает списки посредников.

>>> from itertools import islice
>>> def parts(list_, indices):
...     i = iter(list_)
...     return [list(islice(i, n)) for n in chain(indices, [None])]
7
ответ дан Cide 21 August 2018 в 01:00
поделиться
  • 1
    indicies - & gt; indices – Blixt 29 July 2009 в 08:37
  • 2
    +1 для краткости и для повторного использования значений (enumerate выполняет итерацию существующего массива, в отличие от zip) – Blixt 29 July 2009 в 08:43
  • 3
    Как отметил Бликст, я думаю, что вы имели в виду индексы вместо указаний. Тогда у вас есть незначительная проблема при передаче таких индексов, как [0,5,12,17], и в этом случае ваш результат будет содержать пустой список list_ [0: 0] – Il-Bhima 29 July 2009 в 08:44
  • 4
    @ Il-Bhima: что можно утверждать правильно, так как первая часть равна длине 0, что согласуется с примером OP. – Cide 29 July 2009 в 08:47
  • 5
    @ Ил-Бхима, я думаю, что предполагаемое поведение перехода в "расщепление на индекс 0" было бы получить пустой массив в качестве первого значения split. Лично я ненавижу «волшебство». поведение, которое изменяется в зависимости от параметров. – Blixt 29 July 2009 в 08:48

Cide делает три копии массива: [0] + индексы копируют ([0] + индексы) + [] копирует снова, а индексы [: - 1] копируют в третий раз. Ил-Бхима составляет пять экземпляров. (Я не считаю возвращаемое значение, конечно.)

Эти могут быть уменьшены (izip, islice), но вот версия с нулевой копией:

def iterate_pairs(lst, indexes):
    prev = 0
    for i in indexes:
        yield prev, i
        prev = i
    yield prev, len(lst)

def partition(lst, indexes):
    for first, last in iterate_pairs(lst, indexes):
        yield lst[first:last]

indexes = [5, 12, 17]
lst = range(20)

print [l for l in partition(lst, indexes)]

Of Конечно, копии массивов довольно дешевы (собственный код) по сравнению с интерпретированным Python, но это имеет еще одно преимущество: его легко повторно использовать, чтобы напрямую мутировать данные:

for first, last in iterate_pairs(lst, indexes):
    for i in range(first, last):
        lst[i] = first
print lst
# [0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 12, 12, 12, 12, 12, 17, 17, 17]

(Вот почему я передал индексы iterate_pairs.Если вас это не волнует, вы можете удалить этот параметр и просто иметь окончательную строку: «yield prev, None», который нужен всем разделам ().)

0
ответ дан Glenn Maynard 21 August 2018 в 01:00
поделиться

Это все, что я мог бы подумать о

def partition(list_, indexes):
    if indexes[0] != 0:
        indexes = [0] + indexes
    if indexes[-1] != len(list_):
        indexes = indexes + [len(list_)]
    return [ list_[a:b] for (a,b) in zip(indexes[:-1], indexes[1:])]
0
ответ дан Il-Bhima 21 August 2018 в 01:00
поделиться
  • 1
    Умное решение, очень сжатое =) Я дам ответ на +1 к kjfletch, хотя, потому что он повторно использует существующие значения, в то время как этот метод делает много создания / изменения списка. – Blixt 29 July 2009 в 08:40
  • 2
    Было бы более последовательно отбрасывать условные обозначения - если первый индекс равен 0, первый элемент должен быть пустым. Просто используйте indexes = [0] + indexes + [None]. – Glenn Maynard 29 July 2009 в 08:41
  • 3
    Кроме того, вероятно, лучше с itertools.izip вместо zip, а itertools.islice вместо прямой нарезки. – Glenn Maynard 29 July 2009 в 08:44
  • 4
    @Glenn Хм, я на самом деле пытался избежать пустых списков в начале и в конце. Не уверен, хотел ли это, чтобы оригинальный плакат – Il-Bhima 29 July 2009 в 08:48
  • 5
    не перезаписывать встроенную переменную (список) – dalloliogm 29 July 2009 в 09:09
>>> def burst_seq(seq, indices):
...    startpos = 0
...    for index in indices:
...       yield seq[startpos:index]
...       startpos = index
...    yield seq[startpos:]
...
>>> list(burst_seq(range(20), [5, 12, 17]))
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16], [17, 18, 19]]
>>> list(burst_seq(range(20), []))
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]]
>>> list(burst_seq(range(0), [5, 12, 17]))
[[], [], [], []]
>>>

Maxima mea culpa: он использует оператор for, и он не использует такие вещи, как itertools, zip (), None как часовое, списки, ...

; -)

4
ответ дан John Machin 21 August 2018 в 01:00
поделиться
  • 1
    Причина использования "whizzbang stuff" не потому, что это модно или заставить людей выглядеть умнее, потому что он ближе к декларативной спецификации решения. Конструктивный подход с изменяемым состоянием обычно более подвержен ошибкам ... – fortran 20 May 2013 в 11:03

Мне было бы интересно увидеть более питонический способ сделать это. Но это дрянное решение. Вам нужно будет добавить проверку для списка индексов empry.

Что-то по строкам:

indexes = [5, 12, 17]
list = range(20)

output = []
prev = 0

for index in indexes:
    output.append(list[prev:index])
    prev = index

output.append(list[indexes[-1]:])

print output

производит

[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16], [17, 18, 19]]
8
ответ дан kjfletch 21 August 2018 в 01:00
поделиться
  • 1
    Не очень доволен двумя голосами за то, что бросил идеи в банк. Особенно без комментариев. Я заявил о грубом характере решения. – kjfletch 29 July 2009 в 09:13
  • 2
    Этот сайт не должен допускать downvoting без объяснения причин. Это совсем не полезно. – Glenn Maynard 29 July 2009 в 09:20
  • 3
    Вот почему я ненавижу модное слово «Pythonic». Это похоже на то, что все написанное на Python должно быть написано каким-то специальным способом на языке Python, по какой-то причине желательно насильно раздавить одну строку. – Glenn Maynard 29 July 2009 в 10:25
  • 4
    По-моему, "pythonic" просто означает хороший, идиоматический стиль. Это не означает гиперконденсационные однолинейные решения, которые показывают каждую функцию python. Для меня это выглядит совершенно pythonic. Он использует срезы соответствующим образом, использует диапазон, когда диапазон более уместен, чем xrange, и выполняет итерацию непосредственно над списком, а не зацикливание по индексам. Pythonic? Проверьте. Приемлемый? Проверьте. Точная? Проверьте. +1 – jcdyer 29 July 2009 в 21:54
  • 5
    О, и в python 2 вы можете использовать prev после выхода цикла for, поэтому вы можете заменить output.append(list[indexes[-1]:]) на output.append(list[prev:]). – jcdyer 29 July 2009 в 21:56

Вот еще один ответ.

def partition(l, indexes):
    result, indexes = [], indexes+[len(l)]
    reduce(lambda x, y: result.append(l[x:y]) or y, indexes, 0)
    return result

Он поддерживает отрицательные индексы и т. д.

>>> partition([1,2,3,4,5], [1, -1])
[[1], [2, 3, 4], [5]]
>>> 
0
ответ дан Steve Losh 21 August 2018 в 01:00
поделиться
2
ответ дан anthony 31 October 2018 в 19:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: