#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2013
    Posts
    24
    Rep Power
    0

    Help with consistent spacing in a string


    I have several strings that look like the following:

    Code:
    EVENT: open   HOST: computer_one   DATE: 5/20/13
    EVENT: login - local   HOST: computer_one   DATE: 5/20/13
    EVENT: logoff   HOST: computer_one   DATE: 5/20/13
    and I need them to line up consistently regardless of their length when printed like:

    Code:
    EVENT: open            HOST: computer_one   DATE: 5/20/13
    EVENT: login - local   HOST: computer_one   DATE: 5/20/13
    EVENT: logoff          HOST: computer_one   DATE: 5/20/13
    I'm not sure how to ensure that they line up every time when printed. Using .ljust(#) does not produce consistent results. What is the best way to ensure they line up?
  2. #2
  3. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,931
    Rep Power
    481
    Try this alignment function.
    Code:
    def superspit(S, C):
        '''
            >>> list(superspit('EVENT: open HOST: computer_one DATE: 5/20/13',':'))
            ['EVENT: open', 'HOST: computer_one', 'DATE: 5/20/13']
        '''
        rv = []
        p = len(S)
        for i in range(S.count(C)):
            j = S.rfind(C, 0, p)
            k = S.rfind(' ', 0, j) + 1
            rv.append(S[k:p].strip())
            p = k
        return reversed(rv)
    
    def align(L, C = '.', extra_space = 0):
    
        """
            For printing, aligns the strings in the list L
            based on the positions of the word immediately preceding the character in C.
            It does this by inserting space characters.
            Returns a list of strings.
            >>> S = 'EVENT: open HOST: computer_one DATE: 5/20/13,EVENT: login - local HOST: computer_one DATE: 5/20/13,EVENT: logoff HOST: computer_one DATE: 5/20/13'
            >>> LIST = S.split(',')
            >>> NEW_LIST = align(LIST, ':')
            >>> LF = '{:c}'.format(10)
            >>> print(LF.join(NEW_LIST))
            EVENT: open          HOST: computer_one DATE: 5/20/13
            EVENT: login - local HOST: computer_one DATE: 5/20/13
            EVENT: logoff        HOST: computer_one DATE: 5/20/13
        """
    
        A = [superspit(R, C) for R in L]      # split into fields
        F = [[] for R in L]
        space = extra_space + 1
        for B in zip(*A):
            C = space + max(len(D) for D in B)
            for (i, D,) in enumerate(B):
                F[i].extend([D, ' '*(C - len(D))])
        return [''.join(E) for E in F]
    The doctest for align fails. I don't see the difference. Could be the doctest contains ASCII code 13 I don't see.
    Last edited by b49P23TIvg; May 29th, 2013 at 10:07 PM.
    [code]Code tags[/code] are essential for python code and Makefiles!
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    May 2009
    Posts
    514
    Rep Power
    33
    Assuming that you don't know the width of any of the columns (if you will use a fixed width then skip the first part of the program). You can of course adjust this as you want.
    Code:
    test_data = """EVENT: open   HOST: computer_one   DATE: 5/20/13
    EVENT: login - local   HOST: computer_one   DATE: 5/20/13
    EVENT: logoff   HOST: computer_seven   DATE: 5/20/13"""
    
    ## find longest in the first (EVENT:) and second (HOST:) postition
    first=0
    second=0
    
    ## break each rec into 3 parts and find the length of the first two
    list_of_recs=[]
    for rec in test_data.split("\n"):
        pos = rec.find("HOST:")
        pos2 = rec.find("DATE:", pos+1)
        ## add the 3 parts to a list of lists to be printed separately
        junk_list = [rec[:pos].strip(), rec[pos:pos2].strip(), rec[pos2:].strip()]
        if len(junk_list[0]) > first:
            first = len(junk_list[0])
        if len(junk_list[1]) > second:
            second = len(junk_list[1])
        list_of_recs.append(junk_list)
    
    ## output based on spacing from above
    output_format = "%s-%ds %s-%ds %s-s" % ("%", first, "%", second, "%")
    for rec in list_of_recs:
        print output_format % (rec[0], rec[1], rec[2])
    Last edited by dwblas; May 30th, 2013 at 12:03 AM.

IMN logo majestic logo threadwatch logo seochat tools logo