76 lines
2.2 KiB
Python
76 lines
2.2 KiB
Python
'''Variously aligned columns
|
|
from delimited text.
|
|
'''
|
|
|
|
from functools import reduce
|
|
from itertools import repeat
|
|
|
|
|
|
# TEST ----------------------------------------------------
|
|
# main :: IO ()
|
|
def main():
|
|
'''Test of three alignments.'''
|
|
|
|
txt = '''Given$a$text$file$of$many$lines,$where$fields$within$a$line$
|
|
are$delineated$by$a$single$'dollar'$character,$write$a$program
|
|
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
|
|
column$are$separated$by$at$least$one$space.
|
|
Further,$allow$for$each$word$in$a$column$to$be$either$left$
|
|
justified,$right$justified,$or$center$justified$within$its$column.'''
|
|
|
|
rows = [x.split('$') for x in txt.splitlines()]
|
|
table = paddedRows(max(map(len, rows)))('')(rows)
|
|
|
|
print('\n\n'.join(map(
|
|
alignedTable(table)(' '),
|
|
[-1, 0, 1] # Left, Center, Right
|
|
)))
|
|
|
|
|
|
# alignedTable :: [[String]] -> Alignment -> String -> String
|
|
def alignedTable(rows):
|
|
'''Tabulation of rows of cells, with cell alignment
|
|
specified by:
|
|
eAlign -1 = left
|
|
eAlign 0 = center
|
|
eAlign 1 = right
|
|
and separator between columns
|
|
supplied by the `sep` argument.
|
|
'''
|
|
def go(sep, eAlign):
|
|
lcr = ['ljust', 'center', 'rjust'][1 + eAlign]
|
|
|
|
# nextAlignedCol :: [[String]] -> [String] -> [[String]]
|
|
def nextAlignedCol(cols, col):
|
|
w = max(len(cell) for cell in col)
|
|
return cols + [
|
|
[getattr(s, lcr)(w, ' ') for s in col]
|
|
]
|
|
|
|
return '\n'.join([
|
|
sep.join(cells) for cells in
|
|
zip(*reduce(nextAlignedCol, zip(*rows), []))
|
|
])
|
|
return lambda sep: lambda eAlign: go(sep, eAlign)
|
|
|
|
|
|
# GENERIC -------------------------------------------------
|
|
|
|
# paddedRows :: Int -> a -> [[a]] -> [[a]]
|
|
def paddedRows(n):
|
|
'''A list of rows of even length,
|
|
in which each may be padded (but
|
|
not truncated) to length n with
|
|
appended copies of value v.'''
|
|
def go(v, xs):
|
|
def pad(x):
|
|
d = n - len(x)
|
|
return (x + list(repeat(v, d))) if 0 < d else x
|
|
return [pad(row) for row in xs]
|
|
return lambda v: lambda xs: go(v, xs) if xs else []
|
|
|
|
|
|
# MAIN ---
|
|
if __name__ == '__main__':
|
|
main()
|