アプローチ#1
ワンほとんど*ベクトル化されたアプローチは、それが一緒に行く提案することができ新しい注文に基づいてIDを作成し、分割するように -
def position_based_slice(L):
# Get lengths of each element in input list
lens = np.array([len(item) for item in L])
# Form ID array that has *ramping* IDs within an element starting from 0
# and restarts with a new element at 0
id_arr = np.ones(lens.sum(),int)
id_arr[lens[:-1].cumsum()] = -lens[:-1]+1
# Get order maintained sorted indices for sorting flattened version of list
ids = np.argsort(id_arr.cumsum(),kind='mergesort')
# Get sorted version and split at boundaries decided by lengths of ids
vals = np.take(np.concatenate(L),ids)
cut_idx = np.where(np.diff(ids)<0)[0]+1
return np.split(vals,cut_idx)
*開始時にはループの理解が含まれていますが、リストの入力要素の長さだけを収集することを意図しているため、ランタイム全体への影響は最小限に抑える必要があります。
サンプル実行 -
In [76]: input_list = [[1,2,3,4,5],[2,6,7,8],[1,3,6,7,8],[3,2]]
In [77]: position_based_slice(input_list)
Out[77]:
[array([1, 2, 1, 3]), # input_list[ID=0]
array([2, 6, 3, 2]), # input_list[ID=1]
array([3, 7, 6]), # input_list[ID=2]
array([4, 8, 7]), # input_list[ID=3]
array([5, 8])] # input_list[ID=4]
アプローチ#2
はここで、インデックスに簡単で、オリジナルの入力要素に遡る2D
配列を作成し、別のアプローチです。これは、ブールインデックス付けと一緒にNumPyブロードキャストを使用します。
def position_based_slice_2Dgrid(L):
# Get lengths of each element in input list
lens = np.array([len(item) for item in L])
# Create a mask of valid places in a 2D grid mapped version of list
mask = lens[:,None] > np.arange(lens.max())
out = np.full(mask.shape,-1,dtype=int)
out[mask] = np.concatenate(L)
return out
サンプル実行 - - 実装がこのようなものになりますので
In [126]: input_list = [[1,2,3,4,5],[2,6,7,8],[1,3,6,7,8],[3,2]]
In [127]: position_based_slice_2Dgrid(input_list)
Out[127]:
array([[ 1, 2, 3, 4, 5],
[ 2, 6, 7, 8, -1],
[ 1, 3, 6, 7, 8],
[ 3, 2, -1, -1, -1]])
を、今出力の各列には、IDベースの出力に対応することになります。
これを1行のループで行いますか?または任意のforループが行うでしょうか? – Navid777
ループは実行されますが、データセットはかなり大きいので、速度が問題になる可能性があります。 – Jack
"負の数をマスキングしていますが、これはこれまでのところ私にとってはうまくいきませんでした" - どうしてそれがうまくいかなかったのですか? – Divakar