我想创建一个矩阵,每行从左到右滚动n列,每列k 1s。 (每行中的n-k个元素为0) 示例:
k = 4,n = 10
结果:
1 1 1 1 0 0 0 0 0 0
0 1 1 1 1 0 0 0 0 0
0 0 1 1 1 1 0 0 0 0
0 0 0 1 1 1 1 0 0 0
0 0 0 0 1 1 1 1 0 0
0 0 0 0 0 1 1 1 1 0
0 0 0 0 0 0 1 1 1 1
如何快速,智能地创建此矩阵?
答案 0 :(得分:1)
最佳答案取决于您对“智能”的理解。一种内存有效的方法是跨越一维数组:
>>> import numpy as np
>>> from numpy.lib.stride_tricks import as_strided
>>> a = np.zeros(2*n-k, dtype=int)
>>> a[n-k:n] = 1
>>> view = as_strided(a[n-k:], shape=(n-k+1, n), strides=(-8, 8))
>>> view.tolist()
[[1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1]]
此视图将16个整数存储为70个整数数组。
另一种方法是观察散乱的数组具有4个重复模式,然后是7个零的重复模式。因此,您可以将其平铺并重塑:
>>> r = n-k+1
>>> np.tile([1]*k+[0]*r, r)[:-r].reshape(r,n)
array([[1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1]])
如果您不想使用numpy,并且只是在寻找简单直接的Pythonic方法,则可以滚动deque
并进行累加:
from collections import deque
data = [1]*k + [0]*(n-k)
d = deque(data)
result = [data]
while not d[-1]:
d.rotate(1)
result.append(list(d))
可能有一个listcomp的listcomp-这不是我的,我发现可怜的代码段被遗弃在chatroom #6的寒冷和肮脏的地板上。作者并不喜欢发布它(承认它位于“酷一线”和“不该是一线的东西”之间的模糊线上):
>>> [[1 if 0<=i-j<k else 0 for i in range(n)] for j in range(n-k+1)]
[[1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1]]
答案 1 :(得分:0)
您可以使用列表理解:
[list(map(int, list(bin(2**10 + (2**4 - 1) * 2**expo)[3:]))) for expo in range(6, -1, -1)]
输出:
[[1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1]]