2015-01-16 12 views
0

중첩 목록을 병합하는 방법에는 여러 가지가 있습니다.중첩 목록의 배열 축소 및 평탄화

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

내가 관심을 갖는 것은 목록을 원래 형식으로 재구성하는 역 연산입니다. 예 :

L = [[array([[ 24, -134],[ -67, -207]])], 
    [array([[ 204, -45],[ 99, -118]])], 
    [array([[ 43, -154],[-122, 168]]), array([[ 33, -110],[ 147, -26],[ -49, -122]])]] 

# flattened version 

L_flat = [24, -134, -67, -207, 204, -45, 99, -118, 43, -154, -122, 168, 33, -110, 147, -26, -49, -122] 

인덱스를 저장하고 원래 형식으로 재구성하는 효율적인 방법이 있습니까?

목록은 임의의 깊이 일 수 있으며 규칙적인 모양이 아니어야하며 치수가 다른 배열이 포함됩니다.

물론 배열의 구조와 numpy 배열의 모양을 저장하기 위해 병합 기능을 변경해야합니다.

+1

평평한 버전에서 원래 어떻게 보 였는지 어떻게 알았습니까? 병합 프로세스에서 정보를 잃어 버렸습니다. – jonrsharpe

+0

목록의 구조를 저장하려면 병합 기능을 변경해야합니다. – memecs

+0

어느 정도까지는 자신의 질문에 대답했습니다. 당신은'flatten'을 수정하여리스트의 구조와 그 안에있는 배열의 형태에 관한 정보를 유지할 필요가 있습니다. 예를 들어,''['(2, 2)], ((2, 2)], [(2, 2), (3,2)]]를 반환 할 수 있습니다. 그런 다음'L_flat'을 적절하게 슬라이스하고 각 슬라이스에서 배열을'다시 형성 '해야합니다. – jonrsharpe

답변

1

역설을 구축하는 중입니다. 개체를 병합하려고하지만 개체의 구조 정보를 개체의 어딘가에 유지하면서 개체를 병합하고 싶지는 않습니다.

그래서이 작업을 수행 할 수있는 파이썬 방법은 객체를 평평하게,하지만 당신은 순차적으로 (즉. 플랫 방식) 수있는 __iter__이있을 것이다 클래스 기본 객체의 요소 통과를 작성하는 하지입니다 . 평평한 것으로 변환하는 것만큼이나 빠르며 (요소 당 한 번만 적용되는 경우) 원래의 비평면 컨테이너를 복제하거나 변경하지 않습니다.

0

다음은 중첩 된 목록을 반복하고 개별적으로로드하는 것보다 30 배 빠른 것으로 나타났습니다.

def flatten(nl): 
    l1 = [len(s) for s in itertools.chain.from_iterable(nl)] 
    l2 = [len(s) for s in nl] 

    nl = list(itertools.chain.from_iterable(
     itertools.chain.from_iterable(nl))) 

    return nl,l1,l2 

def reconstruct(nl,l1,l2): 
    return np.split(np.split(nl,np.cumsum(l1)),np.cumsum(l2))[:-1] 

L_flat,l1,l2 = flatten(L) 
L_reconstructed = reconstruct(L_flat,l1,l2) 

더 나은 솔루션 솔루션은 임의의 수의 중첩 수준에 대해 반복적으로 작동합니다.

+0

이유는 무엇입니까? – memecs

2

나는 평평하게하는 솔루션 및 NumPy와 배열의 패턴 화 해제 중첩 된 목록을 찾고,하지만 그래서이 함께했다,이 답이없는 질문을 발견 :

def _flatten(values): 
    if isinstance(values, np.ndarray): 
     yield values.flatten() 
    else: 
     for value in values: 
      yield from _flatten(value) 

def flatten(values): 
    # flatten nested lists of np.ndarray to np.ndarray 
    return np.concatenate(list(_flatten(values))) 

def _unflatten(flat_values, prototype, offset): 
    if isinstance(prototype, np.ndarray): 
     shape = prototype.shape 
     new_offset = offset + np.product(shape) 
     value = flat_values[offset:new_offset].reshape(shape) 
     return value, new_offset 
    else: 
     result = [] 
     for value in prototype: 
      value, offset = _unflatten(flat_values, value, offset) 
      result.append(value) 
     return result, offset 

def unflatten(flat_values, prototype): 
    # unflatten np.ndarray to nested lists with structure of prototype 
    result, offset = _unflatten(flat_values, prototype, 0) 
    assert(offset == len(flat_values)) 
    return result 

예 :

a = [ 
    np.random.rand(1), 
    [ 
     np.random.rand(2, 1), 
     np.random.rand(1, 2, 1), 
    ], 
    [[]], 
] 

b = flatten(a) 

# 'c' will have values of 'b' and structure of 'a' 
c = unflatten(b, a) 

출력 :

a: 
[array([ 0.26453544]), [array([[ 0.88273824], 
     [ 0.63458643]]), array([[[ 0.84252894], 
     [ 0.91414218]]])], [[]]] 
b: 
[ 0.26453544 0.88273824 0.63458643 0.84252894 0.91414218] 
c: 
[array([ 0.26453544]), [array([[ 0.88273824], 
     [ 0.63458643]]), array([[[ 0.84252894], 
     [ 0.91414218]]])], [[]]] 

라이센스 : WTFPL

,