我有一个如下所示的矩阵;
matrix=""" 8 1 A A A A 8
8 5 A A A 3 8
7 2 A A 1 4 7
6 1 3 A 2 5 7
2 4 5 A 1 1 1"""
这是我的代码块:
lines= [i.strip().split() for i in matrix.splitlines()]
lst=[[lines[i][j] for i in range(len(lines))]for j in range(len(lines[0]))]
h=0
while h<=len(lines[0]):
for i in range(len(lines[0])-1,0,-1):
for j in range(len(lines)-1,-1,-1):
for k in lst:
if k.count('A')==len(lines):
if lines[j][i-1]=='A':
lines[j][i-1]=lines[j][i]
lines[j][i]='A'
h+=1
for line in lines:
print(*(i or " " for i in line) , sep=" ")
如果一列充满A,我想将该列移到最右边,但是我的代码将所有A移到右边。这是我的输出:
8 1 8 A A A A
8 5 3 8 A A A
7 2 1 4 7 A A
6 1 3 2 5 7 A
2 4 5 1 1 1 A
我想要这样的输出:
8 1 A A A 8 A
8 5 A A 3 8 A
7 2 A 1 4 7 A
6 1 3 2 5 7 A
2 4 5 1 1 1 A
答案 0 :(得分:6)
您可以use zip()
来转置矩阵,将所有纯"A"
排序到其末端,然后再次用zip()
进行逆转置:
matrix=""" 8 1 A A A A 8
8 5 A A A 3 8
7 2 A A 1 4 7
6 1 3 A 2 5 7
2 4 5 A 1 1 1"""
# string to list of lists of strings
m = [[x.strip() for x in line.split()] for line in matrix.split("\n")]
print(*m,sep="\n")
# transpose and sort
t_m = [list(line) for line in zip(*m)]
t_m.sort(key = lambda x: all(k=="A" for k in x))
# reverse transpose
m = [list(line) for line in zip(*t_m)]
print(*m,sep="\n")
输出:
# before
['8', '1', 'A', 'A', 'A', 'A', '8']
['8', '5', 'A', 'A', 'A', '3', '8']
['7', '2', 'A', 'A', '1', '4', '7']
['6', '1', '3', 'A', '2', '5', '7']
['2', '4', '5', 'A', '1', '1', '1']
# after
['8', '1', 'A', 'A', 'A', '8', 'A']
['8', '5', 'A', 'A', '3', '8', 'A']
['7', '2', 'A', '1', '4', '7', 'A']
['6', '1', '3', '2', '5', '7', 'A']
['2', '4', '5', '1', '1', '1', 'A']
转置后的数据如下:
# before sorting
['8', '8', '7', '6', '2']
['1', '5', '2', '1', '4']
['A', 'A', 'A', '3', '5']
['A', 'A', 'A', 'A', 'A'] # this is the column you want to sort behind all others
['A', 'A', '1', '2', '1']
['A', '3', '4', '5', '1']
['8', '8', '7', '7', '1']
# after sort
['8', '8', '7', '6', '2']
['1', '5', '2', '1', '4']
['A', 'A', 'A', '3', '5']
['A', 'A', '1', '2', '1']
['A', '3', '4', '5', '1']
['8', '8', '7', '7', '1']
['A', 'A', 'A', 'A', 'A'] # now it is here
sort/sorting之所以起作用,是因为如果整个行都由True
('A'
)组成,而所有其他行都是True == 1
,那么它只有False == 0
。
排序是稳定,因此它不会更改评估False
的行之间的相对顺序。
答案 1 :(得分:3)
首先,让我们定义用于转置类似列表的实用工具功能
def transpose(elements):
return list(map(list, zip(*elements)))
然后根据规则定义排序键:如果列表元素等于'A',则它排在最后,否则将其保持在原始位置
def sorting_key(indexed_row):
return all(element == 'A' for element in indexed_row[1]), indexed_row
之后,我们的解决方案将是
>>> from operator import itemgetter
>>> transpose(map(itemgetter(1), sorted(enumerate(transpose(lines)),
key=sorting_key)))
这给了我们
[['8', '1', 'A', 'A', 'A', '8', 'A'],
['8', '5', 'A', 'A', '3', '8', 'A'],
['7', '2', 'A', '1', '4', '7', 'A'],
['6', '1', '3', '2', '5', '7', 'A'],
['2', '4', '5', '1', '1', '1', 'A']]
或@PatrickArtner指出,sorted
使用Timsort,即stable algorithm,因此我们不需要处理非全“ A”列的情况在其原始位置并定义:
def sorting_key(row):
return all(element == 'A' for element in row)
在那之后我们可以简单地写
>>> transpose(sorted(transpose(lines),
key=sorting_key))
答案 2 :(得分:3)
这是使用numpy
的一种方式:
s = np.array([x.strip() for x in matrix.split()]).reshape(5,7)
print(s)
array[['8', '1', 'A', 'A', 'A', 'A', '8'],
['8', '5', 'A', 'A', 'A', '3', '8'],
['7', '2', 'A', 'A', '1', '4', '7'],
['6', '1', '3', 'A', '2', '5', '7'],
['2', '4', '5', 'A', '1', '1', '1']]
您可以使用np.flatnonzero
来找到all
值为0
的列,并用最后一个交换它们:
m = np.flatnonzero((s == 'A').all(axis=0))[0]
s.T[[m, s.shape[1]-1]] = s.T[[s.shape[1]-1, m]]
array([['8', '1', 'A', '8', 'A', 'A', 'A'],
['8', '5', 'A', '8', 'A', '3', 'A'],
['7', '2', 'A', '7', '1', '4', 'A'],
['6', '1', '3', '7', '2', '5', 'A'],
['2', '4', '5', '1', '1', '1', 'A']], dtype='<U21')