2013-07-05 3 views
7

Я попробовал все (в моем знании) от разделения массива и объединить их вместе и даже при использовании itertools:Как преобразовать вложенный список в одномерный список в Python?

import itertools 

def oneDArray(x): 
    return list(itertools.chain(*x)) 

Результат я хочу:

) print oneDArray([1,[2,2,2],4]) == [1,2,2,2,4]

Как ни странно, он работает для

b) print oneDArray([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) == [1, 2, 3, 4, 5, 6, 7, 8, 9]

Вопрос 1) Как я могу получить часть а работать так, как я хочу (любые намеки?)

Вопрос 2) Почему следующий код выше работы для части б и не пункт а ??

+0

Возможный дубликат [Сплав (нерегулярный) список списков в Python] (http://stackoverflow.com/questions/2158395/flatten-an-irregular-list-of-lists-in-python) – TerryA

+1

Я мог бы Я не нашел ответ, который я искал в SO, потому что ни один из моих результатов поиска не возвращал ничего о «сплющивании», но приведенные здесь ответы помогли прояснить многое! – compski

ответ

7

Вам нужно рекурсивно пройти цикл по списку и проверить, является ли элемент итерируемым (строки также повторяются, но пропускают их) или нет.

itertools.chain не будет работать для [1,[2,2,2],4], потому что это требует, чтобы все это предметы, чтобы быть итерацию, но 1 и 4 (целые числа) не итерацию. Вот почему он работал для второго, потому что это список списков.

>>> from collections import Iterable 
def flatten(lis): 
    for item in lis: 
     if isinstance(item, Iterable) and not isinstance(item, basestring): 
      for x in flatten(item): 
       yield x 
     else:   
      yield item 

>>> lis = [1,[2,2,2],4] 
>>> list(flatten(lis)) 
[1, 2, 2, 2, 4] 
>>> list(flatten([[1, 2, 3], [4, 5, 6], [7, 8, 9]])) 
[1, 2, 3, 4, 5, 6, 7, 8, 9] 

Работы для любого уровня вложенности:

>>> a = [1,[2,2,[2]],4] 
>>> list(flatten(a)) 
[1, 2, 2, 2, 4] 

В отличие от других решений, это будет работать для строк, а также:

>>> lis = [1,[2,2,2],"456"] 
>>> list(flatten(lis)) 
[1, 2, 2, 2, '456'] 
+0

Спасибо, ваше решение было самым ясным и отвечало на мои вопросы! – compski

+0

@compski рад, что помогло. :) –

1

itertools.chain() итерацию каждого элемента в введенном списке (обратитесь к документам, которые я связал). Поскольку вы не можете перебирать целые числа, возникает ошибка. Вот почему во втором примере у вас есть только списки в списке и не целые числа, поэтому целые числа фактически не повторяются.

Чтобы получить его работу, вы можете использовать рекурсию:

>>> from collections import Iterable 
>>> def flat(lst): 
...  for parent in lst: 
...   if not isinstance(i, Iterable): 
...    yield parent 
...   else: 
...    for child in flat(parent): 
...     yield child 
... 
>>> list(flat(([1,[2,2,2],4])) 
[1, 2, 2, 2, 4] 
0

Это на самом деле довольно легко, без использования itertools, вы можете просто перебрать список и если цикл будет сталкиваться с другим списком, вы будете просто перебрать вложенную список. Вот код:

def flatten(l): 
    flatList = [] 
    for elem in l: 
     # if an element of a list is a list 
     # iterate over this list and add elements to flatList 
     if type(elem) == list: 
      for e in elem: 
       flatList.append(e) 
     else: 
      flatList.append(elem) 
    return flatList 


a = [1,[2,2,2],4] # flatten(a) returns [1, 2, 2, 2, 4] 
b = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # flatten(b) returns [1, 2, 3, 4, 5, 6, 7, 8, 9] 
+0

Не работает для '[1, [2,2, [2]], 4]'. –

0

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

lis = [1,[2,2,2],"456"] 
output = [] 
for item in lis: 
    if isinstance(item, (str, int, bool)): 
     output.append(item) 
    elif isinstance(item, dict): 
     for i in item.items(): 
      output.extend(i) 
    else: 
     output.extend(list(item)) 

Почему я простираться (список (пункт)), что даже если в ваших товарах есть набор, это не вызовет никаких проблем. Это будет обрабатывать элементы как string, integer, boolean, dictionary, list, а также кортеж.

8

Если вы используете python < 3, то вы можете сделать следующее:

from compiler.ast import flatten 
list = [1,[2,2,2],4] 
print flatten(list) 

В ручной эквивалент в Python 3.0 будет (из this answer):

def flatten(x): 
    result = [] 
    for el in x: 
     if hasattr(el, "__iter__") and not isinstance(el, str): 
      result.extend(flatten(el)) 
     else: 
      result.append(el) 
    return result 

print(flatten(["junk",["nested stuff"],[],[[]]])) 

Можно даже сделать то же самое в списке понимание:

list = [1,[2,2,2],4] 
l = [item for sublist in list for item in sublist] 

Что является эквивалентом:

l = [[1], [2], [3], [4], [5]] 
result = [] 
for sublist in l: 
    for item in sublist: 
     result.append(item) 

print(result) 
+1

Что импорт «compiler.ast» взорвал мой разум! ... это даже проще, чем все ответы, которые включали в себя урожай. Но одна вещь, хотя я попробовал перечислить список answe (что я идеально хочу получить ответ в этой форме, так как я сделал Haskell раньше), но вы дали «TypeError: Объект 'int' не является итерируемым "= ( – compski

0
old_list = [1,2,3,['a','b'],4,5,6,['c','d',[11,22,33,'aa','bb','cc',[111,222,333,['aaa','bbb','ccc',[1111,2222,['aaaa','bbbb',[11111,22222]]]]]],'e']] 

new_list = [] 

def my_fun(temp_list): 
    for ele in temp_list: 
     if type(ele) == list: 
      my_fun(ele) 
     else: 
      new_list.append(ele) 


my_fun(old_list) 
print old_list 
print new_list 

output: 
old_list = [1, 2, 3, ['a', 'b'], 4, 5, 6, ['c', 'd', [11, 22, 33, 'aa', 'bb', 'cc', [111, 222, 333, ['aaa', 'bbb', 'ccc', [1111, 2222, ['aaaa', 'bbbb', [11111, 22222]]]]]], 'e']] 
new_list = [1, 2, 3, 'a', 'b', 4, 5, 6, 'c', 'd', 11, 22, 33, 'aa', 'bb', 'cc', 111, 222, 333, 'aaa', 'bbb', 'ccc', 1111, 2222, 'aaaa', 'bbbb', 11111, 22222, 'e'] 

Используйте рекурсию для преобразования нескольких вложенных списков в один разреженный список.

Смежные вопросы