Ответ 1
На сегодняшний день самое быстрое (и самое короткое) решение опубликовано:
list(sum(output, ()))
Около 50% быстрее, чем решение itertools
, и примерно на 70% быстрее, чем решение map
.
В Sqlite команда "select..from" возвращает результат "output", который печатает (в python):
>>print output
[(12.2817, 12.2817), (0, 0), (8.52, 8.52)]
Кажется, это список кортежей. Я хотел бы преобразовать "выходные данные" в простой одномерный массив (= список в Python, я думаю):
[12.2817, 12.2817, 0, 0, 8.52, 8.52]
или матрица 2х3:
12.2817 12.2817
0 0
8.52 8.52
быть прочитанным через "output [i] [j]"
Команда flatten не выполняет работу для первого варианта, и я понятия не имею для второго... :)
Не могли бы вы дать мне подсказку? Что-то быстрое было бы здорово, так как реальные данные намного больше (вот простой пример).
На сегодняшний день самое быстрое (и самое короткое) решение опубликовано:
list(sum(output, ()))
Около 50% быстрее, чем решение itertools
, и примерно на 70% быстрее, чем решение map
.
Подход к пониманию списков, который работает с типами Iterable и работает быстрее, чем другие методы, показанные здесь.
flattened = [item for sublist in l for item in sublist]
l
- список для выравнивания (называется output
в случае OP)
l = list(zip(range(99), range(99))) # list of tuples to flatten
[item for sublist in l for item in sublist]
результат timeit = 7,67 мкс ± 129 нс за цикл
flattened = []
list(flattened.extend(item) for item in l)
результат timeit = 11 мкс ± 433 нс за цикл
list(sum(l, ()))
результат timeit = 24,2 мкс ± 269 нс за цикл
В Python 3 вы можете использовать синтаксис *
, чтобы сгладить список итераций:
>>> t = [ (1,2), (3,4), (5,6) ]
>>> t
[(1, 2), (3, 4), (5, 6)]
>>> import itertools
>>> list(itertools.chain(*t))
[1, 2, 3, 4, 5, 6]
>>>
Или вы можете сгладить список следующим образом:
reduce(lambda x,y:x+y, map(list, output))
использовать цепочку itertools
:
>>> import itertools
>>> list(itertools.chain.from_iterable([(12.2817, 12.2817), (0, 0), (8.52, 8.52)]))
[12.2817, 12.2817, 0, 0, 8.52, 8.52]
>>> flat_list = []
>>> nested_list = [(1, 2, 4), (0, 9)]
>>> for a_tuple in nested_list:
... flat_list.extend(list(a_tuple))
...
>>> flat_list
[1, 2, 4, 0, 9]
>>>
вы можете легко перейти из списка кортежей в один список, как показано выше.
Обновление: Сглаживание с использованием расширения, но без понимания и без использования списка в качестве итератора (самый быстрый)
После проверки следующего ответа на этот вопрос, который обеспечил более быстрое решение с помощью понимания списка с помощью dual for
я сделал небольшую настройку, и теперь она работает лучше: сначала выполнение списка (...) тянуло большой процент времени, а затем изменялось. понимание списка для простой циклы побрило также немного больше.
Новое решение:
l = []
for row in output: l.extend(row)
Старшая:
Сглаживание с картой/расширение:
l = []
list(map(l.extend, output))
Сглаживание с пониманием списка вместо карты
l = []
list(l.extend(row) for row in output)
Некоторое время для нового расширения и улучшения можно получить, просто удалив список (...) для [...]:
import timeit
t = timeit.timeit
o = "output=list(zip(range(1000000000), range(10000000))); l=[]"
steps_ext = "for row in output: l.extend(row)"
steps_ext_old = "list(l.extend(row) for row in output)"
steps_ext_remove_list = "[l.extend(row) for row in output]"
steps_com = "[item for sublist in output for item in sublist]"
print("new extend: ", t(steps_ext, setup=o, number=10))
print("old extend w []: ", t(steps_ext_remove_list, setup=o, number=10))
print("comprehension: ", t(steps_com, setup=o, number=10,))
print("old extend: ", t(steps_ext_old, setup=o, number=10))
>>> new extend: 4.502427191007882
>>> old extend w []: 5.281140706967562
>>> comprehension: 5.54302118299529
>>> old extend: 6.840151469223201
Это то, для чего была создана numpy
, как с точки зрения структуры данных, так и с точки зрения скорости.
import numpy as np
output = [(12.2817, 12.2817), (0, 0), (8.52, 8.52)]
output_ary = np.array(output) # this is your matrix
output_vec = output_ary.ravel() # this is your 1d-array
В случае произвольных вложенных списков (на всякий случай):
def flatten(lst):
result = []
for element in lst:
if hasattr(element, '__iter__'):
result.extend(flatten(element))
else:
result.append(element)
return result
>>> flatten(output)
[12.2817, 12.2817, 0, 0, 8.52, 8.52]