2016-12-25 64 views
4

我有一組數字,我要對齊考慮逗號:對齊的數字

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,但我不知道如何將逗號之前一個逗號和rjust後ljust,無論是在同一串。

如何在不使用format()的情況下解決此問題? (我想與ljust和rjust一致)

+0

@ JimFasarakis - 希利亞德,確保str.center將是確定。但是,對齊中心沒有上述結果。 – Reman

+0

@ JimFasarakis-Hilliard你爲什麼要刪除你的答案?看起來不錯。我希望這只是暫時的。關於'sum(,[])':我發現可以使用,但問題是它每次都會執行'a = a + b'而不是'a + = b'。 –

回答

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)) 

最後,我們appendr

 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

不錯,但計算最大字符串長度的方法效率很低:列表上的sum值不是很好(最好使用'itertools.chain'),並且不必爲此創建一個新列表,只需執行'l = max(len(x)for l in mylist for x in l)' –

+0

'chain'確實是最好的。我在這裏接受你的第二個建議,不要導入任何東西。在這種情況下,我總是拿出'sum(..,[])'出於某種原因,它吸引我:-) –

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 ', ' ') 
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 ', ' ']