class Table:
def __init__(self, meta, tups):
self._validate_data(meta, tups) # валидация введенных данных
self.meta = list(meta)
self.tables = list(tups)
def _validate_data(self, meta, tups):
'''Валидация данных'''
if len(meta) != len(tups[0]):
raise ValueError('Meta header and tuples lengths dont match!')
if not all(len(tups[0]) == len(x) for x in tups):
raise ValueError('All tuples must be the same length!')
def _find_lengths(self):
'''Поиск максимальной длины каждой колонки. Вспомогательная функция'''
result = [0 for _ in range(len(self.tables[0]))]
merged = [self.meta] + self.tables
for i in range(len(merged[0])):
for row in merged:
if len(str(row[i])) > result[i]:
result[i] = len(str(row[i]))
return result
def _draw_border(self):
''' "Рисует" рамку таблицы '''
rows = ['' for _ in range((len(self.tables)+1)*2+1)]
lengths = self._find_lengths()
for i in range(len(rows)):
if i % 2 == 0: # если строка четная, значит там очертания рамки
rows[i] = '+'
for num in lengths:
rows[i] += '-'*num + '--+'
else: # если нечетная, значит там будут данные
rows[i] = '|'
for num in lengths:
rows[i] += ' '*num + ' |'
return rows # возвращаем список строк таблицы
def draw_table(self):
'''Рисует таблицу целиком'''
from itertools import count
merged = [self.meta] + self.tables
table = self._draw_border() # подготавливаем рамку заранее
lengths = self._find_lengths() # нужно, чтобы знать максимальную длину каждой колонки
for i, idx in zip(range(1, len(table), 2), count()): # итерация по индексам списка table и индексам списка merged
result = '|'
for j, elem in enumerate(merged[idx]):
extra_l = (lengths[j] - len(str(elem))) // 2
extra_r = extra_l+1 if (lengths[j] - len(str(elem))) % 2 != 0 else extra_l
result += ' ' + ' '*extra_l + str(elem) + ' '*extra_r + ' |'
table[i] = result
print('\n'.join(table))
if __name__ == '__main__':
meta = ['id', 'name', 'description', 'count']
tups = [
(1, 'tomato', 'shit', '2000'),
(24, 'pineapple', 'good', '13000'),
(7, 'watermelon', 'eatable', '600')
]
t = Table(meta, tups)
t.draw_table()
Y2xhc3MgVGFibGU6CiAgICBkZWYgX19pbml0X18oc2VsZiwgbWV0YSwgdHVwcyk6CiAgICAgICAgc2VsZi5fdmFsaWRhdGVfZGF0YShtZXRhLCB0dXBzKSAgIyDQstCw0LvQuNC00LDRhtC40Y8g0LLQstC10LTQtdC90L3Ri9GFINC00LDQvdC90YvRhQogICAgICAgIHNlbGYubWV0YSA9IGxpc3QobWV0YSkKICAgICAgICBzZWxmLnRhYmxlcyA9IGxpc3QodHVwcykKCiAgICBkZWYgX3ZhbGlkYXRlX2RhdGEoc2VsZiwgbWV0YSwgdHVwcyk6CiAgICAgICAgJycn0JLQsNC70LjQtNCw0YbQuNGPINC00LDQvdC90YvRhScnJwogICAgICAgIGlmIGxlbihtZXRhKSAhPSBsZW4odHVwc1swXSk6CiAgICAgICAgICAgIHJhaXNlIFZhbHVlRXJyb3IoJ01ldGEgaGVhZGVyIGFuZCB0dXBsZXMgbGVuZ3RocyBkb250IG1hdGNoIScpCiAgICAgICAgaWYgbm90IGFsbChsZW4odHVwc1swXSkgPT0gbGVuKHgpIGZvciB4IGluIHR1cHMpOgogICAgICAgICAgICByYWlzZSBWYWx1ZUVycm9yKCdBbGwgdHVwbGVzIG11c3QgYmUgdGhlIHNhbWUgbGVuZ3RoIScpCgogICAgZGVmIF9maW5kX2xlbmd0aHMoc2VsZik6CiAgICAgICAgJycn0J/QvtC40YHQuiDQvNCw0LrRgdC40LzQsNC70YzQvdC+0Lkg0LTQu9C40L3RiyDQutCw0LbQtNC+0Lkg0LrQvtC70L7QvdC60LguINCS0YHQv9C+0LzQvtCz0LDRgtC10LvRjNC90LDRjyDRhNGD0L3QutGG0LjRjycnJwogICAgICAgIHJlc3VsdCA9IFswIGZvciBfIGluIHJhbmdlKGxlbihzZWxmLnRhYmxlc1swXSkpXQogICAgICAgIG1lcmdlZCA9IFtzZWxmLm1ldGFdICsgc2VsZi50YWJsZXMKICAgICAgICBmb3IgaSBpbiByYW5nZShsZW4obWVyZ2VkWzBdKSk6CiAgICAgICAgICAgIGZvciByb3cgaW4gbWVyZ2VkOgogICAgICAgICAgICAgICAgaWYgbGVuKHN0cihyb3dbaV0pKSA+IHJlc3VsdFtpXToKICAgICAgICAgICAgICAgICAgICByZXN1bHRbaV0gPSBsZW4oc3RyKHJvd1tpXSkpCiAgICAgICAgcmV0dXJuIHJlc3VsdAoKICAgIGRlZiBfZHJhd19ib3JkZXIoc2VsZik6CiAgICAgICAgJycnICLQoNC40YHRg9C10YIiINGA0LDQvNC60YMg0YLQsNCx0LvQuNGG0YsgJycnCiAgICAgICAgcm93cyA9IFsnJyBmb3IgXyBpbiByYW5nZSgobGVuKHNlbGYudGFibGVzKSsxKSoyKzEpXQogICAgICAgIGxlbmd0aHMgPSBzZWxmLl9maW5kX2xlbmd0aHMoKQogICAgICAgIGZvciBpIGluIHJhbmdlKGxlbihyb3dzKSk6CiAgICAgICAgICAgIGlmIGkgJSAyID09IDA6ICAjINC10YHQu9C4INGB0YLRgNC+0LrQsCDRh9C10YLQvdCw0Y8sINC30L3QsNGH0LjRgiDRgtCw0Lwg0L7Rh9C10YDRgtCw0L3QuNGPINGA0LDQvNC60LgKICAgICAgICAgICAgICAgIHJvd3NbaV0gPSAnKycKICAgICAgICAgICAgICAgIGZvciBudW0gaW4gbGVuZ3RoczoKICAgICAgICAgICAgICAgICAgICByb3dzW2ldICs9ICctJypudW0gKyAnLS0rJwogICAgICAgICAgICBlbHNlOiAgIyDQtdGB0LvQuCDQvdC10YfQtdGC0L3QsNGPLCDQt9C90LDRh9C40YIg0YLQsNC8INCx0YPQtNGD0YIg0LTQsNC90L3Ri9C1CiAgICAgICAgICAgICAgICByb3dzW2ldID0gJ3wnCiAgICAgICAgICAgICAgICBmb3IgbnVtIGluIGxlbmd0aHM6CiAgICAgICAgICAgICAgICAgICAgcm93c1tpXSArPSAnICcqbnVtICsgJyAgfCcKICAgICAgICByZXR1cm4gcm93cyAgIyDQstC+0LfQstGA0LDRidCw0LXQvCDRgdC/0LjRgdC+0Log0YHRgtGA0L7QuiDRgtCw0LHQu9C40YbRiwoKICAgIGRlZiBkcmF3X3RhYmxlKHNlbGYpOgogICAgICAgICcnJ9Cg0LjRgdGD0LXRgiDRgtCw0LHQu9C40YbRgyDRhtC10LvQuNC60L7QvCcnJwogICAgICAgIGZyb20gaXRlcnRvb2xzIGltcG9ydCBjb3VudAogICAgICAgIG1lcmdlZCA9IFtzZWxmLm1ldGFdICsgc2VsZi50YWJsZXMKICAgICAgICB0YWJsZSA9IHNlbGYuX2RyYXdfYm9yZGVyKCkgICMg0L/QvtC00LPQvtGC0LDQstC70LjQstCw0LXQvCDRgNCw0LzQutGDINC30LDRgNCw0L3QtdC1CiAgICAgICAgbGVuZ3RocyA9IHNlbGYuX2ZpbmRfbGVuZ3RocygpICAjINC90YPQttC90L4sINGH0YLQvtCx0Ysg0LfQvdCw0YLRjCDQvNCw0LrRgdC40LzQsNC70YzQvdGD0Y4g0LTQu9C40L3RgyDQutCw0LbQtNC+0Lkg0LrQvtC70L7QvdC60LgKICAgICAgICBmb3IgaSwgaWR4IGluIHppcChyYW5nZSgxLCBsZW4odGFibGUpLCAyKSwgY291bnQoKSk6ICAjINC40YLQtdGA0LDRhtC40Y8g0L/QviDQuNC90LTQtdC60YHQsNC8INGB0L/QuNGB0LrQsCB0YWJsZSDQuCDQuNC90LTQtdC60YHQsNC8INGB0L/QuNGB0LrQsCBtZXJnZWQKICAgICAgICAgICAgcmVzdWx0ID0gJ3wnCiAgICAgICAgICAgIGZvciBqLCBlbGVtIGluIGVudW1lcmF0ZShtZXJnZWRbaWR4XSk6CiAgICAgICAgICAgICAgICBleHRyYV9sID0gKGxlbmd0aHNbal0gLSBsZW4oc3RyKGVsZW0pKSkgLy8gMgogICAgICAgICAgICAgICAgZXh0cmFfciA9IGV4dHJhX2wrMSBpZiAobGVuZ3Roc1tqXSAtIGxlbihzdHIoZWxlbSkpKSAlIDIgIT0gMCBlbHNlIGV4dHJhX2wKICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnICcgKyAnICcqZXh0cmFfbCArIHN0cihlbGVtKSArICcgJypleHRyYV9yICsgJyB8JwogICAgICAgICAgICB0YWJsZVtpXSA9IHJlc3VsdAogICAgICAgIHByaW50KCdcbicuam9pbih0YWJsZSkpCgoKaWYgX19uYW1lX18gPT0gJ19fbWFpbl9fJzoKICAgIG1ldGEgPSBbJ2lkJywgJ25hbWUnLCAnZGVzY3JpcHRpb24nLCAnY291bnQnXQogICAgdHVwcyA9IFsKICAgICAgICAoMSwgJ3RvbWF0bycsICdzaGl0JywgJzIwMDAnKSwKICAgICAgICAoMjQsICdwaW5lYXBwbGUnLCAnZ29vZCcsICcxMzAwMCcpLAogICAgICAgICg3LCAnd2F0ZXJtZWxvbicsICdlYXRhYmxlJywgJzYwMCcpCiAgICBdCiAgICB0ID0gVGFibGUobWV0YSwgdHVwcykKICAgIHQuZHJhd190YWJsZSgp