0

Excel table = this is the excel file screenshot which is how final result should be. Please take closer look at "Lifestyle" section.

I can't figure out how to make my python just like the excel picture screenshot. "Lifestyle" section needs to have 2 more sub-columns combined just like in a picture below. Any help would be appreciated.

I'm gonna post picture below PyCharm screenshot:

Here is my code:

#convert inches to feet-inches
def inch_to_feet(x):
    feet = x // 12
    inch = x % 12
    return str(feet)+"'"+str(inch)+'"'


#file opened
print("Hello")
roster = input("Please enter a roster file: ")

if roster != "roster_extended.csv":
    print("Invalid name")

elif roster == "roster_extended.csv":
    additional_name = input("There are 13 lines in this file. Would you like to enter an additional names? (Y/N): ")
    if additional_name == "Y":
        input("How many more names?: ")

infile = open("roster_extended.csv", 'r')

b = infile.readline()
b = infile.readlines()
header = '{0:>12} {1:>35} {2:>3} {3:>16} {4:>5} {5:>3} {6:>9}'.format("FirstName","LastName","Age","Occupation","Ht","Wt","lifestyle")
print(header)

with open("roster_extended.csv", "a+") as infile:
     b = infile.write(input("Enter first name: "))

for person in b:
    newperson = person.replace("\n", "").split(",")
    newperson[4] = eval(newperson[4])
    newperson[4] = inch_to_feet(newperson[4])
    newperson

    formatted='{0:>12} {1:>35} {2:>3} {3:>16} {4:>5} {5:>3} {6:>9}'.format(newperson[0],newperson[1],newperson[2],newperson[3],newperson[4],newperson[5],newperson[6])

    print(formatted)

Here is the output I get:

FirstName                            LastName Age       Occupation    Ht  Wt lifestyle

    Anna                             Barbara  35            nurse  5'3" 129          
Catherine                                  Do  45        physicist  5'5" 135          
    Eric                           Frederick  28          teacher  5'5" 140          
 Gabriel                           Hernandez  55          surgeon  5'7" 150         x
     Ivy                                 Joo  31         engineer  5'2" 126         x
   Kelly                               Marks  21          student  5'4" 132          
   Nancy                               Owens  60     immunologist  5'8" 170         x
Patricia                                 Qin  36 dental assistant 4'11" 110         x
Roderick                           Stevenson  51       bus driver  5'6" 160         x
   Tracy                          Umfreville  42      audiologist  5'7" 156         x
Victoria Wolfeschlegelsteinhausenbergerdorff  38     data analyst  5'8" 158          
    Lucy                                  Xi  49        professor  5'9" 161          
 Yolanda                             Zachary  58        secretary 5'10" 164         x
bad_coder
  • 11,289
  • 20
  • 44
  • 72
  • 4
    Please include the code in the post instead of posting an image of it. That way those seeking to help you can simply copy-past the code directly, and it will also show in search. – bad_coder Jan 24 '20 at 05:12

1 Answers1

0

Brief explanation of the solution:

You gave tabulated data as input (there are several ways to tabulate: check here). Since you're starting with python the solution keeps within standard library (thus not resorting to external libraries). Only format() and class variables are used to keep track of column width (if you delete elements you'll want to update the variables.) This programmatically automates tabulation.

Since you are starting out, I recommend putting a breakpoint in __init__() and __new__() to observe their behavior.

I used Enum because conceptually it's the right tool for the job. You only need to understand Enum.name and Enum.value, as for everything else consider it a normal class.

There are 2 output files, one in tabulated form and the other in barebone csv.

(For the most part the solution is "canonical" (or close). The procedural part was rushed, but gives a sufficient idea.)

import csv
import codecs
from enum import Enum
from pathlib import Path


IN_FILE = Path("C:\\your_path\\input.csv")
OUT_FILE = Path("C:\\your_path\\output1.csv")
OUT_FILE_TABULATE = Path("C:\\your_path\\output2.csv")


def read_csv(file) -> list:

    with open(file) as csv_file:
        reader_csv = csv.reader(csv_file, delimiter=',')
        for row in reader_csv:
            yield row


def write_file(file, result_ordered):

    with codecs.open(file, "w+", encoding="utf-8") as file_out:
        for s in result_ordered:
            file_out.write(s + '\n')


class LifeStyle(Enum):

    Sedentary = 1
    Active = 2
    Moderate = 3

    def to_list(self):
        list_life_style = list()

        for one_style in LifeStyle:
            if one_style is self:
                list_life_style.append('x')
            else:
                list_life_style.append('')

        return list_life_style

    def tabulate(self):

        str_list_life_style = list()

        for one_style in LifeStyle:
            if one_style is not self:
                str_list_life_style.append('{: ^{width}}'.format(' ', width=len(one_style.name)))
            else:
                str_list_life_style.append('{: ^{width}}'.format('x', width=len(self.name)))

        return str_list_life_style

    def tabulate_single_column(self):
        return '{: >{width}}'.format(str(self.name), width=len(LifeStyle.Sedentary.name))

    @staticmethod
    def header_single_column():
        return ' {}'.format(LifeStyle.__name__)

    @staticmethod
    def header():
        return ' {} {} {}'.format(
            LifeStyle.Sedentary.name,
            LifeStyle.Active.name,
            LifeStyle.Moderate.name,
        )


class Person:

    _FIRST_NAME = "First Name"
    _LAST_NAME = "Last Name"
    _AGE = "Age"
    _OCCUPATION = "Occupation"
    _HEIGHT = "Height"
    _WEIGHT = "Weight"

    max_len_first_name = len(_FIRST_NAME)
    max_len_last_name = len(_LAST_NAME)
    max_len_occupation = len(_OCCUPATION)

    def __new__(cls, first_name, last_name, age, occupation, height, weight, lifestyle):
        cls.max_len_first_name = max(cls.max_len_first_name, len(first_name))
        cls.max_len_last_name = max(cls.max_len_last_name, len(last_name))
        cls.max_len_occupation = max(cls.max_len_occupation, len(occupation))

        return super().__new__(cls)

    def __init__(self, first_name, last_name, age, occupation, height, weight, lifestyle):
        self.first_name = first_name
        self.last_name = last_name
        self.age = age
        self.occupation = occupation
        self.height = height
        self.weight = weight
        self.lifestyle = lifestyle

    @classmethod
    def _tabulate_(cls, first_name, last_name, age, occupation, height, weight):
        first_part = '{: >{m_first}} {: >{m_last}} {: >{m_age}} {: <{m_occup}} {: <{m_height}} {: >{m_weight}}'.format(
            first_name,
            last_name,
            age,
            occupation,
            height,
            weight,
            m_first=Person.max_len_first_name,
            m_last=Person.max_len_last_name,
            m_occup=Person.max_len_occupation,
            m_age=len(Person._AGE),
            m_height=len(Person._HEIGHT),
            m_weight=len(Person._WEIGHT))

        return first_part

    @classmethod
    def header(cls, header_life_style):
        first_part = Person._tabulate_(Person._FIRST_NAME, Person._LAST_NAME, Person._AGE, Person._OCCUPATION,
                                       Person._HEIGHT, Person._WEIGHT)

        return '{}{}'.format(first_part, header_life_style)

    def __str__(self):
        first_part = Person._tabulate_(self.first_name, self.last_name, self.age, self.occupation, self.height,
                                       self.weight)

        return '{}{}'.format(first_part, ' '.join(self.lifestyle.tabulate()))

    def single_column(self):
        first_part = Person._tabulate_(self.first_name, self.last_name, self.age, self.occupation, self.height,
                                       self.weight)

        return '{} {}'.format(first_part, self.lifestyle.tabulate_single_column())


def populate(persons_populate):

    for line in read_csv(IN_FILE):

        life_style = ''

        if line[6] == 'x':
            life_style = LifeStyle.Sedentary
        elif line[7] == 'x':
            life_style = LifeStyle.Moderate
        elif line[8] == 'x':
            life_style = LifeStyle.Active

        persons_populate.append(Person(line[0], line[1], line[2], line[3], line[4], line[5], life_style))

    return persons_populate


persons = populate(list())

print(Person.header(LifeStyle.header()))

for person in persons:
    print(person)

write_file(OUT_FILE_TABULATE, [str(item) for item in persons])

# add new persons here
persons.append(Person("teste", "teste", "22", "worker", "5'8\"", "110", LifeStyle.Active))

final_list = list()

for person in persons:
    one_list = [person.first_name, person.last_name, person.age, person.occupation, person.height,
                person.weight]
    one_list.extend([item.strip() for item in person.lifestyle.tabulate()])
    final_list.append(','.join(one_list))

write_file(OUT_FILE, final_list)

print("\n", Person.header(LifeStyle.header_single_column()))

for person in persons:
    print(person.single_column())

output1.csv:

Anna,Barbara,35,nurse,5'3",129,,,x
Catherine,Do,45,physicist,5'5",135,,x,
Eric,Frederick,28,teacher,5'5",140,,,x
Gabriel,Hernandez,55,surgeon,5'7",150,x,,
Ivy,Joo,31,engineer,5'2",126,x,,
Kelly,Marks,21,student,5'4",132,,x,
Nancy,Owens,60,immunologist,5'8",170,x,,
Patricia,Qin,36,dental assistant,4'11",110,x,,
Roderick,Stevenson,51,bus driver,5'6",160,x,,
Tracy,Umfreville,42,audiologist,5'7",156,x,,
Victoria,Wolfeschlegelsteinhausenbergerdorff,38,data analyst ,5'8",158,,,x
Lucy,Xi,49,professor,5'9",161,,,x
Yolanda,Zachary,58,secretary,5'10",164,x,,
teste,teste,22,worker,5'8",110,,x,

output2.csv:

      Anna                             Barbara  35 nurse            5'3"      129                    x    
 Catherine                                  Do  45 physicist        5'5"      135            x            
      Eric                           Frederick  28 teacher          5'5"      140                    x    
   Gabriel                           Hernandez  55 surgeon          5'7"      150    x                    
       Ivy                                 Joo  31 engineer         5'2"      126    x                    
     Kelly                               Marks  21 student          5'4"      132            x            
     Nancy                               Owens  60 immunologist     5'8"      170    x                    
  Patricia                                 Qin  36 dental assistant 4'11"     110    x                    
  Roderick                           Stevenson  51 bus driver       5'6"      160    x                    
     Tracy                          Umfreville  42 audiologist      5'7"      156    x                    
  Victoria Wolfeschlegelsteinhausenbergerdorff  38 data analyst     5'8"      158                    x    
      Lucy                                  Xi  49 professor        5'9"      161                    x    
   Yolanda                             Zachary  58 secretary        5'10"     164    x                    

single_column:

      Anna                             Barbara  35 nurse            5'3"      129  Moderate
 Catherine                                  Do  45 physicist        5'5"      135    Active
      Eric                           Frederick  28 teacher          5'5"      140  Moderate
   Gabriel                           Hernandez  55 surgeon          5'7"      150 Sedentary
       Ivy                                 Joo  31 engineer         5'2"      126 Sedentary
     Kelly                               Marks  21 student          5'4"      132    Active
     Nancy                               Owens  60 immunologist     5'8"      170 Sedentary
  Patricia                                 Qin  36 dental assistant 4'11"     110 Sedentary
  Roderick                           Stevenson  51 bus driver       5'6"      160 Sedentary
     Tracy                          Umfreville  42 audiologist      5'7"      156 Sedentary
  Victoria Wolfeschlegelsteinhausenbergerdorff  38 data analyst     5'8"      158  Moderate
      Lucy                                  Xi  49 professor        5'9"      161  Moderate
   Yolanda                             Zachary  58 secretary        5'10"     164 Sedentary
     teste                               teste  22 worker           5'8"      110    Active
bad_coder
  • 11,289
  • 20
  • 44
  • 72