2015-01-16 79 views
0

有许多用于拼合嵌套列表的配方。我将复制一个解决方案在这里仅供参考:拼合并解开numpy数组的嵌套列表

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] 

是否有一种有效的扁平化方法,可以节省指标并重建为原始格式?

请注意,该列表可以是任意深度,并且可能不具有规则形状,并且将包含不同维度的数组。

当然,flattening函数也应该改变,以存储列表的结构和numpy数组的形状。

+1

你应该从扁平版本中知道它最初的样子?你在扁平化过程中失去了信息。 – jonrsharpe

+0

当然,应该更改展平功能以存储列表的结构。 – memecs

+0

某种程度上,你已经回答了你自己的问题;你需要修改'flatten'来提供关于列表结构和其中数组形状的保留信息。例如,它可以在平展的“L”旁边返回'[[(2,2)],[(2,2)],[(2,2),(3,2)]]''。然后,您将不得不相应地切分“L_flat”并对每个切片的阵列进行“重塑”。 – jonrsharpe

回答

1

您正在构建一个悖论:您想要展平该对象,但不想展平该对象,并在对象的某个位置保留其结构信息。

所以Python的方式做,这是扁平化的对象,但写一个类,将有一个__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的阵列unflatten嵌套列表,但只发现这个没有答案的问题,所以我想出了这个:

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