сгладить список списка через понимание списка

Я пытаюсь сгладить список, используя понимание списка в python. Мой список чем-то похож

[[1, 2, 3], [4, 5, 6], 7, 8]

только для печати отдельного элемента в этом списке списка я написал этот код

   def flat(listoflist):
     for item in listoflist:
             if type(item) != list:
                     print item
             else:
                     for num in item:
                             print num  
>>> flat(list1)
1
2
3
4
5
6
7
8

Затем я использовал ту же логику, чтобы сгладить свой список с помощью понимания списка. Я получаю следующую ошибку.

    list2 = [item if type(item) != list else num for num in item for item in list1]
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: 'int' object is not iterable

Как я могу сгладить этот тип списка, используя понимание списка?


person Anurag Sharma    schedule 27.06.2013    source источник


Ответы (5)


>>> from collections import Iterable
>>> from itertools import chain

Один лайнер:

>>> list(chain.from_iterable(item if isinstance(item,Iterable) and
                    not isinstance(item, basestring) else [item] for item in lis))
[1, 2, 3, 4, 5, 6, 7, 8]

Читаемая версия:

>>> def func(x):                                         #use `str` in py3.x 
...     if isinstance(x, Iterable) and not isinstance(x, basestring): 
...         return x
...     return [x]
... 
>>> list(chain.from_iterable(func(x) for x in lis))
[1, 2, 3, 4, 5, 6, 7, 8]
#works for strings as well
>>> lis = [[1, 2, 3], [4, 5, 6], 7, 8, "foobar"]
>>> list(chain.from_iterable(func(x) for x in lis))                                                                
[1, 2, 3, 4, 5, 6, 7, 8, 'foobar']

Использование понимания вложенного списка: (будет медленным по сравнению с itertools.chain):

>>> [ele for item in (func(x) for x in lis) for ele in item]
[1, 2, 3, 4, 5, 6, 7, 8, 'foobar']
person Ashwini Chaudhary    schedule 27.06.2013
comment
Это отлично подходит для спрашивающего, использующего 2.x, но стоит отметить, что пользователи 3.x должны использовать str вместо basestring. - person Gareth Latty; 27.06.2013
comment
@Ashwini Что делать, если мои элементы имеют тип dict вместо integer? - person Anurag Sharma; 28.06.2013
comment
@AnuragSharma небольшой пример? - person Ashwini Chaudhary; 28.06.2013
comment
@AshwiniChaudhary, например ---› [[{'ascdd': 'skj'}, {'fd': 'srsr'}], {'dsf': 'ds', 'ds': 'dsffd'}] - person Anurag Sharma; 28.06.2013
comment
@AnuragSharma, каков ожидаемый результат в этом случае? - person Ashwini Chaudhary; 28.06.2013
comment
@AshwiniChaudhary ожидаемый результат ---› [{'ascdd': 'skj'}, {'fd': 'srsr'}, {'dsf': 'ds', 'ds': 'dsffd'}] или просто список словарей - person Anurag Sharma; 28.06.2013

Никто не дал обычного ответа:

def flat(l):
  return [y for x in l for y in x]

В StackOverflow есть дубликаты этого вопроса.

person GreenAsJade    schedule 02.01.2014
comment
Ваш код не работает для списка, предоставленного OP, потому что его список включает неитерируемые объекты, а именно целые числа. Однако ваш код работает, если каждый элемент в списке является итерируемым объектом. Смотрите мой комментарий ниже. - person JDG; 26.05.2015
comment
Спасибо, что указали на это - мне действительно нужно найти момент, чтобы возиться с этим и взяться за дело... - person GreenAsJade; 27.05.2015

Альтернативное решение с использованием генератора:

import collections

def flatten(iterable):
    for item in iterable:
        if isinstance(item, collections.Iterable) and not isinstance(item, str):  # `basestring` < 3.x
            yield from item  # `for subitem in item: yield item` < 3.3
        else:
            yield item

>>> list(flatten([[1, 2, 3], [4, 5, 6], 7, 8]))
[1, 2, 3, 4, 5, 6, 7, 8]
person Gareth Latty    schedule 27.06.2013

Вы пытаетесь перебрать число, чего не можете сделать (отсюда и ошибка).

Если вы используете Python 2.7:

>>> from compiler.ast import flatten
>>> flatten(l)
[1, 2, 3, 4, 5, 6, 7, 8]

Но обратите внимание, что модуль теперь устарел и больше не существует в Python 3.

person TerryA    schedule 27.06.2013
comment
Списки проверки типов — плохая идея. Это делает его гораздо менее гибким. - person Gareth Latty; 27.06.2013
comment
если l равно [[1, 2, 3], [4, 5, 6], 7, 888], первое решение дает [1, 2, 3, 4, 5, 6, 7, 8, 8, 8]. - person falsetru; 27.06.2013
comment
Удален первый бит, но жаль, что мое другое решение не будет работать в python 3. - person TerryA; 27.06.2013

person    schedule
comment
Наверное, объяснение тоже не помешало бы. - person scopchanov; 24.08.2018
comment
В этом решении используется рекурсия. Для каждого элемента во вложенном списке вы проверяете, является ли этот элемент целым числом или списком. Если целое число, мы добавляем это целое число в список nn. Если элемент во вложенном списке является списком, вызовите рекурсивную функцию, вы сделаете с подсписком то же, что и с исходным вложенным списком. Затем снова добавьте элементы, которые не являются списком, в nn. Вывод nn будет невложенным списком. Всем удачного кодинга! - person Alessandro Anderson; 25.08.2018
comment
Большой! Теперь, пожалуйста, отредактируйте свой ответ, добавив эту информацию. - person scopchanov; 25.08.2018
comment
Готово - Намасте. - person Alessandro Anderson; 25.08.2018