developer tip

"튜플 목록"을 일반 목록 또는 행렬로 변환

copycodes 2020. 12. 28. 08:26
반응형

"튜플 목록"을 일반 목록 또는 행렬로 변환


Sqlite를 사용하면 "select..from"명령은 결과 "출력"을 반환하며 다음과 같이 인쇄합니다 (python).

>>print output
[(12.2817, 12.2817), (0, 0), (8.52, 8.52)]

튜플 목록 인 것 같습니다. 간단한 1D 배열에서 "출력"을 변환하고 싶습니다 (= Python의 목록).

[12.2817, 12.2817, 0, 0, 8.52, 8.52]

또는 2x3 매트릭스 :

12.2817 12.2817
0          0 
8.52     8.52

"output [i] [j]"를 통해 읽습니다.

flatten 명령은 첫 번째 옵션에 대한 작업을 수행하지 않으며 두 번째 옵션에 대해서는 전혀 모릅니다 ... :)

힌트를 주시겠습니까? 실제 데이터가 훨씬 더 크기 때문에 빠른 것이 좋습니다 (여기에 간단한 예가 있습니다).


지금까지 가장 빠르고 가장 짧은 솔루션이 게시되었습니다.

list(sum(output, ()))

itertools솔루션 보다 약 50 % 빠르며 솔루션 보다 약 70 % 빠릅니다 map.


Iterable 유형과 함께 작동하고 여기에 표시된 다른 방법보다 빠른 목록 이해 접근 방식입니다.

flattened = [item for sublist in l for item in sublist]

l병합 할 목록입니다 ( outputOP의 경우 호출 됨 ).


timeit 테스트 :

l = list(zip(range(99), range(99)))  # list of tuples to flatten

목록 이해

[item for sublist in l for item in sublist]

timeit 결과 = 루프 당 7.67µs ± 129ns

목록 extend () 메서드

flattened = []
list(flattened.extend(item) for item in l)

timeit 결과 = 루프 당 11µs ± 433ns

합집합()

list(sum(l, ()))

timeit 결과 = 루프 당 24.2µs ± 269ns


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]
>>> 

위와 같이 튜플 목록에서 단일 목록으로 쉽게 이동할 수 있습니다.


업데이트 : 확장을 사용하지만 이해하지 않고 목록을 반복자로 사용하지 않고 병합 (가장 빠름)

After checking the next answer to this that provided a faster solution via a list comprehension with dual for I did a little tweak and now it performs better, first the execution of list(...) was dragging a big percentage of time, then changing a list comprehension for a simple loop shaved a bit more as well.

The new solution is:

l = []
for row in output: l.extend(row)

Older:

Flattening with map/extend:

l = []
list(map(l.extend, output))

Flattening with list comprehension instead of map

l = []
list(l.extend(row) for row in output)

some timeits for new extend and the improvement gotten by just removing list(...) for [...]:

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    

This is what numpy was made for, both from a data structures, as well as speed perspective.

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

In case of arbitrary nested lists(just in case):

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]

ReferenceURL : https://stackoverflow.com/questions/10632839/transform-list-of-tuples-into-a-flat-list-or-a-matrix

반응형