HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Python line condenser function

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
condenserfunctionpythonline

Problem

This is a function I just wrote that tries to condense a set of strings into grouped lines. It actually works, but looks ugly. Is there a better way to achieve the same thing?

Take 4 filtering empty strings first and dropping the if line on the final yield

def mergeToLines(strings, length=40, sep="    "):
    strs = (st for st in sorted(strings, key=len, reverse=True) if st)
    line = strs.next()
    for s in strs:
        if (len(line) + len(s) + len(sep)) >= length:
            yield line
            line = s
        else:
            line += sep + s
    yield line


The idea is that it takes a bunch of strings, and combines them into lines about as long as lineLength. Each line has one or more of the original strings in it, but how many isn't clear until I actually get to slotting them in. Also, note that if a single entry in the list is longer than lineLength, it's still added as its own line (dropping elements is not an option here).

Solution

RECURSIVE SOLUTION:
NOTE: it assumes that the input strings is already sorted. You could sort this at every call of the function, but this seems like unnecessary overhead.

def recursiveMerge(strings=[], current_line='', line_length=40, result=[]):
    """ Gather groups of strings into a line length of approx. 40 """

    # base case
    if not strings:
        result.append(current_line)
        return result

    else:
        next_line = strings.pop(0)

        # if current_line + next_line < line_length, add them
        # otherwise append current_line to result
        if len(current_line + next_line) < line_length:
            current_line = '    '.join([current_line, next_line]).lstrip(' ')    
        else:
            result.append(current_line)
            current_line = next_line

        # recursively call function
        return recursiveMerge(strings, current_line = current_line, result=result)


ITERATIVE SOLUTION:

def myMerge(strings, line_length=40, res=[]):
    """ Gather groups of strings into a line length of approx. 40 """

    # sort the list of string by len
    strings = sorted(strings, key=len, reverse=True)

    # loop through the group of strings, until all have been used
    current_line = strings.pop(0)
    while strings:
        next_line = strings.pop(0)

        # if current_line + next_line shorter than line_length, add them
        # otherwise, append current_line to the result

        if len(current_line + next_line) < line_length:
            current_line = '    '.join([current_line, next_line])
        else:
            res.append(current_line)
            current_line = next_line

    # add any remaining lines to result     
    res.append(current_line)

    return res

Code Snippets

def recursiveMerge(strings=[], current_line='', line_length=40, result=[]):
    """ Gather groups of strings into a line length of approx. 40 """

    # base case
    if not strings:
        result.append(current_line)
        return result

    else:
        next_line = strings.pop(0)

        # if current_line + next_line < line_length, add them
        # otherwise append current_line to result
        if len(current_line + next_line) < line_length:
            current_line = '    '.join([current_line, next_line]).lstrip(' ')    
        else:
            result.append(current_line)
            current_line = next_line

        # recursively call function
        return recursiveMerge(strings, current_line = current_line, result=result)
def myMerge(strings, line_length=40, res=[]):
    """ Gather groups of strings into a line length of approx. 40 """

    # sort the list of string by len
    strings = sorted(strings, key=len, reverse=True)

    # loop through the group of strings, until all have been used
    current_line = strings.pop(0)
    while strings:
        next_line = strings.pop(0)

        # if current_line + next_line shorter than line_length, add them
        # otherwise, append current_line to the result

        if len(current_line + next_line) < line_length:
            current_line = '    '.join([current_line, next_line])
        else:
            res.append(current_line)
            current_line = next_line

    # add any remaining lines to result     
    res.append(current_line)

    return res

Context

StackExchange Code Review Q#25508, answer score: 3

Revisions (0)

No revisions yet.