Доступ к непоследовательным множественным записям в списке списков - PullRequest
2 голосов
/ 18 июня 2019

У меня есть матрица из M векторов, где каждый вектор имеет размер N (NxM).У меня также есть логический вектор размера L> = M, с точно M входами = True.Я хочу создать список списков и поместить M векторов, где логический вектор равен True, в том же порядке, что и в матрице, а остальные я хочу, чтобы они были пустыми списками

Пример: M = 3,N = 4, L = 5

mat = np.array([[1, 5, 9],
               [2, 6, 10],
               [3, 7, 11],
               [4, 8, 12]])
mask = [True, False, True, True, False]

Я хочу создать следующее:

res = [ [1, 2, 3, 4], [], [5, 6, 7, 8], [9, 10, 11, 12], []]

Доступ к нему можно выполнить с помощью:

data = [res[idx] for idx in range(len(res)) if mask(idx)]

Однако,создать его немного проблематично.Я попытался создать список пустых списков, но не могу получить доступ ко всем соответствующим записям одновременно.Есть ли элегантный способ сделать это?

Ответы [ 3 ]

2 голосов
/ 18 июня 2019

Вот как бы я это сделал:

mi = iter(mat.T.tolist())
[(m or []) and next(mi) for m in mask]
# [[1, 2, 3, 4], [], [5, 6, 7, 8], [9, 10, 11, 12], []]
1 голос
/ 18 июня 2019

Мы могли бы использовать np.split для некоторой элегантности , вот так -

In [162]: split_cols = np.split(mat.T,np.cumsum(mask)[:-1])

In [163]: split_cols
Out[163]: 
[array([[1, 2, 3, 4]]),
 array([], shape=(0, 4), dtype=int64),
 array([[5, 6, 7, 8]]),
 array([[ 9, 10, 11, 12]]),
 array([], shape=(0, 4), dtype=int64)]

Итак, это дает нам список 2Dмассивы.Для желаемого вывода списка списков нам нужно сопоставить их с такими -

In [164]: list(map(list,(map(np.ravel,split_cols))))
Out[164]: [[1, 2, 3, 4], [], [5, 6, 7, 8], [9, 10, 11, 12], []]

В качестве альтернативы, мы можем использовать lambda, если для некоторых это выглядит более элегантно -

In [165]: F = lambda a: np.ravel(a).tolist()

In [166]: list(map(F,split_cols))
Out[166]: [[1, 2, 3, 4], [], [5, 6, 7, 8], [9, 10, 11, 12], []]
1 голос
/ 18 июня 2019

Поскольку вы уже используете понимание списка для получения данных от res , я бы сделал аналогичную вещь, чтобы создать res в первую очередь .

mask_cs = np.cumsum(mask) - 1  # array([0, 0, 1, 2, 2]) , gives the corresponding index in mat
res = [mat[:, mask_cs[idx]].tolist() if mask[idx] else [] for idx in range(L)]

В качестве альтернативы, которая одновременно обращается ко всем столбцам мата, можно создать промежуточный массив размером [N, L]

import numpy as np
res = np.zeros((N, L))  # Create result array
res[:, mask] = mat      # Copy the data at the right positions
res = res.T.tolist()    # Transform the array to a list of lists
for idx in range(L):    # Replace the columns with empty lists, if mask[idx] is False
    if not mask[idx]:
        res[idx] = []
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...