Вопрос по flatten, python, list – Как свести гетерогенный список списка в один список в Python?

4

У меня есть список объектов, где объекты могут быть списками или скалярами. Я хочу плоский список только с скалярами. Например:

L = [35,53,[525,6743],64,63,[743,754,757]]
outputList = [35,53,525,6743,64,63,743,754,757]

Постскриптум Ответы на этот вопрос не работают для разнородных списков.Сглаживание мелкого списка в Python

возможный дубликатFlatten (an irregular) list of lists in Python Fred Foo
это работает, если pop () возвращает только один скаляр за разstackoverflow.com/a/10546929/1321404  Вы можете изменить этот код, если len (return_pop_element) & gt; 1 затем снова вызвать рекурсивную функцию для return_pop_element (list). Dmitry Zagorulkin
смотрите такжеstackoverflow.com/a/40857703/4531270 pylang

Ваш Ответ

11   ответов
0

Рекурсивная функция, которая учитывает бесконечную глубину дерева:

def flatten(l):
    if isinstance(l,(list,tuple)):
        if len(l):
            return flatten(l[0]) + flatten(l[1:])
        return []
    else:
        return [l]

>>>flatten([35,53,[525,[1,2],6743],64,63,[743,754,757]])
[35, 53, 525, 1, 2, 6743, 64, 63, 743, 754, 757]

Я пытался избежать isinstance, чтобы учесть универсальные типы, но старая версия имела бы бесконечный цикл для строк. Теперь он корректно выравнивает строки (теперь не по символам, а как будто он притворяется, что строка является скаляром).

Я не ожидал бы, что строки будут сплющены (разбиты на отдельные символы).
Технически строки являются итеративными, поэтому я включил их. Это кажется странным, когда я смотрю на это более внимательно.
0

Это решение предназначено только для вашей конкретной ситуации (скаляры в списках) и предполагает, что скаляры целочисленные. Это ужасное решение, но оно невероятно короткое.

outputlist = map(int,",".split(str(L).replace("[","").replace("]","")))
0
def nchain(iterable):
    for elem in iterable:
        if type(elem) is list:
            for elem2 in elem:
                yield elem2
        else:
            yield elem
4

это можно сделать аккуратно в одну строку, используяnumpy

import numpy as np
np.hstack(l)

вы в конечном итоге с ndarray

array([  35,   53,  525, 6743,   64,   63,  743,  754,  757])
8

Вот относительно простая рекурсивная версия, которая сгладит любую глубину списка

l = [35,53,[525,6743],64,63,[743,754,757]]

def flatten(xs):
    result = []
    if isinstance(xs, (list, tuple)):
        for x in xs:
            result.extend(flatten(x))
    else:
        result.append(xs)
    return result

print flatten(l)
and not isinstance(xs,basestring) для питона & lt; 3, но да хорошая идея
Я думаю, что могу сделать этоisinstance(xs,collections.Iterable) and not isinstance(xs,str) так что включаетset и другие возможные итерируемые также. balki
0
>>> L = [35,53,[525,6743],64,63,[743,754,757]]
>>> K = []
>>> [K.extend([i]) if type(i) == int else K.extend(i) for i in L ]
[None, None, None, None, None, None]
>>> K
[35, 53, 525, 6743, 64, 63, 743, 754, 757]
3
l = [35,53,[525,6743],64,63,[743,754,757]]
outputList = []

for i in l:
    if isinstance(i, list):
        outputList.extend(i)
    else:
        outputList.append(i)
Да, но, конечно, они заполняются редактором, когда вы все равно нажимаете клавишу Tab. Обычно он установлен на 4 или 3 по умолчанию. Также по какой-то причине я не могу написать @Vikas в начале своих комментариев, я не знаю, почему он не позволяет мне ...
@jamylak, спасибо за ссылку. Я всегда думал, что рекомендуется использовать пробелы. Не знал, что это было 4 места.
@jamylak, спасибо за редактирование, но мне нравятся два пробела для отступа :-(
3
>>> data = [35,53,[525,6743],64,63,[743,754,757]]
>>> def flatten(L):
        for item in L:
            if isinstance(item,list):
                for subitem in item:
                    yield subitem
            else:
                yield item


>>> list(flatten(data))
[35, 53, 525, 6743, 64, 63, 743, 754, 757]

Вот однострочная версия для целей игры в гольф (она не очень хорошо выглядит: D)

>>> [y for x in data for y in (x if isinstance(x,list) else [x])]
[35, 53, 525, 6743, 64, 63, 743, 754, 757]
@JanneKarila Это не говорит, что будут строки.
Первая версия разбивает строки на символы, я не думаю, что это желательно.
Это говоритscalars
@JanneKarila Хорошо, теперь это исправлено.
Если вы используетеhasattr(item, '__iter__') Вы можете избежать строковой проблемы, не ограничивая диапазон итераций.
0

Ответ довольно прост. Воспользуйтесь рекурсией.

def flatten(nst_lst, final_list):

    for val in nst_lst:
        if isinstance(val, list):
            flatten(val, final_list)
        else:
            final_list.append(val)
    return final_list

#Sample usage
fl_list = []
lst_to_flatten = [["this",["a",["thing"],"a"],"is"],["a","easy"]]

print(flatten(lst_to_flatten, fl_list))
1

Вот один из вариантов, основанный навопрос, который вы упомянули:

list(itertools.chain(*((sl if isinstance(sl, list) else [sl]) for sl in l)))

UPDATE: И полностью основанная на итераторах версия:

from itertools import imap, chain
list(chain.from_iterable(imap(lambda x: x if isinstance(x, list) else [x], l)))
Это как бы ранит мои глаза.
@JoelCornett +1 Я тоже об этом думал, но мне это не понравилось, так как он должен создавать новый список каждую итерацию.
Это единственный, он не должен быть красивым.
Ну, в таком случае, я думаю, что у меня есть меньший вкладыш, я опубликую его.
Дополнительно,sum((i if isinstance(i, list) else [i] for i in L), [])
1
outputList = []
for e in l:
    if type(e) == list:
        outputList += e
    else:
        outputList.append(e)

>>> outputList
[35, 53, 525, 6743, 64, 63, 743, 754, 757]

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