考虑到逗号我想要对齐一组数字:
10 3
200 4000,222 3 1,5
200,21 0,3 2
30000 4,5 1
mylist = [['10', '3', '', ''],
['200', '4000,222', '3', '1,5'],
['200,21', '', '0,3', '2'],
['30000', '4,5', '1', '']]
我想要的是考虑逗号来对齐此列表:
预期结果:
mylist = [[' 10 ', ' 3 ', ' ', ' '],
[' 200 ', '4000,222', '3 ', '1,5'],
[' 200,21', ' ', '0,3', '2 '],
['30000 ', ' 4,5 ', '1 ', ' ']]
我试图打开清单:
mynewlist = list(zip(*mylist))
并找到每个子列表中逗号后面最长的部分:
for m in mynewlist:
max([x[::-1].find(',') for x in m]
并使用rjust和ljust但我不知道如何在逗号之前调整并在逗号之前调整,两者都在同一个字符串中。
如何在不使用format()的情况下解决此问题? (我想与ljust和rjust保持一致)
答案 0 :(得分:2)
这是目前正在采用的另一种方法。不幸的是,我看不到任何简单的方法来完成这项工作,可能是因为时间: - )
无论哪种方式,我都会解释它。 r
是事先创建的结果列表。
r = [[] for i in range(4)]
然后我们遍历这些值并使用enumerate
:
for ind1, vals in enumerate(zip(*mylist)):
在循环内部,我们获取存在的十进制数字的最大长度和单词的最大长度(单词w / o十进制数字):
l = max(len(v.partition(',')[2]) for v in vals) + 1
mw = max(len(v if ',' not in v else v.split(',')[0]) for v in vals)
现在我们遍历元组vals
中的值并构建我们的结果(是的,目前无法想到避免这种嵌套的方法)。
for ind2, v in enumerate(vals):
如果它包含逗号,则格式应不同。具体来说,我们rjust
基于单词mw
的最大长度,然后添加十进制数字和所需的任何空白区域:
if ',' in v:
n, d = v.split(',')
v = "".join((n.rjust(mw),',', d, " " * (l - 1 - len(d))))
在相反的情况下,我们只需.rjust
然后添加空格:
else:
v = "".join((v.rjust(mw) + " " * l))
最后,我们append
到r
。
r[ind1].append(v)
所有在一起:
r = [[] for i in range(4)]
for ind1, vals in enumerate(zip(*mylist)):
l = max(len(v.partition(',')[2]) for v in vals) + 1
mw = max(len(v if ',' not in v else v.split(',')[0]) for v in vals)
for ind2, v in enumerate(vals):
if ',' in v:
n, d = v.split(',')
v = "".join((n.rjust(mw),',', d, " " * (l - 1 - len(d))))
else:
v = "".join((v.rjust(mw) + " " * l))
r[ind1].append(v)
现在,我们可以打印出来:
>>> print(*map(list,zip(*r)), sep='\n)
[' 10 ', ' 3 ', ' ', ' ']
[' 200 ', '4000,222', '3 ', '1,5']
[' 200,21', ' ', '0,3', '2 ']
['30000 ', ' 4,5 ', '1 ', ' ']
答案 1 :(得分:1)
这适用于python 2和3.虽然我没有使用ljust或rjust,我只是在数字之前和之后添加了尽可能多的空格,因为缺少了列中的最大大小数字:
mylist = [['10', '3', '', ''],
['200', '4000,222', '3', '1,5'],
['200,21', '', '0,3', '2'],
['30000', '4,5', '1', '']]
transposed = list(zip(*mylist))
sizes = [[(x.index(",") if "," in x else len(x), len(x) - x.index(",") if "," in x else 0)
for x in l] for l in transposed]
maxima = [(max([x[0] for x in l]), max([x[1] for x in l])) for l in sizes]
withspaces = [
[' ' * (maxima[i][0] - sizes[i][j][0]) + number + ' ' * (maxima[i][1] - sizes[i][j][1])
for j, number in enumerate(l)] for i, l in enumerate(transposed)]
result = list(zip(*withspaces))
在python3中打印结果:
>>> print(*result, sep='\n')
(' 10 ', ' 3 ', ' ', ' ')
(' 200 ', '4000,222', '3 ', '1,5')
(' 200,21', ' ', '0,3', '2 ')
('30000 ', ' 4,5 ', '1 ', ' ')
答案 2 :(得分:1)
这是一个有点不同的解决方案,它不转置my_list
,而是迭代两次。在第一次传递时,它会生成一个元组列表,每列一个。每个元组是一对数字,其中第一个数字是逗号之前的长度,第二个数字是逗号和数字的长度。一切都跟着它。例如'4000,222'
结果为(4, 4)
。在第二次传递时,它根据第一次传递时生成的格式信息格式化数据。
from functools import reduce
mylist = [['10', '3', '', ''],
['200', '4000,222', '3', '1,5'],
['200,21', '', '0,3', '2'],
['30000', '4,5', '1', '']]
# Return tuple (left part length, right part length) for given string
def part_lengths(s):
left, sep, right = s.partition(',')
return len(left), len(sep) + len(right)
# Return string formatted based on part lengths
def format(s, first, second):
left, sep, right = s.partition(',')
return left.rjust(first) + sep + right.ljust(second - len(sep))
# Generator yielding part lengths row by row
parts = ((part_lengths(c) for c in r) for r in mylist)
# Combine part lengths to find maximum for each column
# For example data it looks like this: [[5, 3], [4, 4], [1, 2], [1, 2]]
sizes = reduce(lambda x, y: [[max(z) for z in zip(a, b)] for a, b in zip(x, y)], parts)
# Format result based on part lengths
res = [[format(c, *p) for c, p in zip(r, sizes)] for r in mylist]
print(*res, sep='\n')
输出:
[' 10 ', ' 3 ', ' ', ' ']
[' 200 ', '4000,222', '3 ', '1,5']
[' 200,21', ' ', '0,3', '2 ']
['30000 ', ' 4,5 ', '1 ', ' ']