Home > Software engineering >  Function to split strings into multiline strings
Function to split strings into multiline strings

Time:10-21

Question: Write the function wordWrap(text, width) which takes a string text containing only lowercase letters or spaces and a positive integer width, and returns a possibly-multiline string that matches the original string, only with line wrapping at the given width. For example, wordWrap('abc', 3) just returns 'abc', but wordWrap('abc', 2) returns a 2-line string, with 'ab' on the first line and 'c' on the second line.

All spaces should be converted to dashes ('-'), so they can be easily seen in the resulting string.

For example, wordWrap('abcdefghij', 4) returns

'''\
abcd
efgh
ij'''

and wordWrap('a b c de fg', 4) returns

'''\
a-b-
c-de
-fg'''

This is my code so far:

def wordWrap(text, width):
    result = ''
    line = ''
    for i in text:
        if i.isalpha():
            line  = i
            if len(line) == width:
                result  = line
                line = ''
                a = text.index(i)
                
                if (a 1) != len(text):
                    result  = '\n'
                    
                if len(text) - (a 1) < width:
                    for n in text[a 1:]:
                        if n.isalpha:
                            result  = n
                        if n.isspace():
                            result  = '-'
                    
        if i.isspace():
            line  = '-'
            if len(line) == width:
                result  = line
                line = ''
                a = text.index(i)
                
                if (a 1) != len(text):
                    result  = '\n'
                    
                if len(text) - (a 1) < width:
                    for n in text[a 1:]:
                        if n.isalpha:
                            result  = n
                        if n.isspace():
                            result  = '-'

    return result


# wordWrap('a b c de fg', 4) returns
'''\
a-b-
c-de
 -fg'''

Where is that extra space in the last line coming from?

CodePudding user response:

When completing the second line, the state of your code is:

line == 'c-de'
result == 'a-b-\n'
i == 'e'
width == 4

What then executes:

if len(line) == width:  # this is True
    result  = line  # result is now 'a-b-\nc-de'
    line = ''
    a = text.index(i)  # a is now 7
    if (a   1) != len(text):  # this is True, a is not the length of text
         result  = '\n'  # result is now 'a-b-\nc-de\n'
    if len(text) - (a   1) < width:  # this is True, 3 < 4
        for n in text[a   1:]:  # looping over ' fg'
            if n.isalpha:  # this is True, because you're not calling the function
                result  = n  # here the problem arises

So, the problem is really just a typo - you wanted if n.isalpha(): where you wrote if n.isalpha:. The value of a function is truthy, it evaluates to True - the result of a function call depends on the return value.

However, the whole solution is needlessly complicated, the function below does the same:

def word_wrap(text, width):
    text = text.replace(' ', '-')
    return '\n'.join(text[i:i width] for i in range(0, len(text), width))


print(word_wrap('a b c de fg', 4))

Output:

a-b-
c-de
-fg

I noted that your code example initially had a misspelled function name, which suggests you're probably not using an IDE (like VSCode or PyCharm), but some other form of editor.

Using an IDE prevents such mistakes, but will also provide warnings and hints that can avoid other common mistakes. As it happens, the specific function of not calling a function isn't caught by PyCharm, but what it does point out is that you've replicated a 14-line piece of code.

'DRY' (don't repeat yourself) is a good programming principle to follow, and writing shorter, more concise code in a good editor makes it easier to catch the kind of mistake that caused you trouble.

Also, a good IDE will allow you to debug the code step-by-step, which is what I did to provide an explanation of your issue. Stepping through with a debugger, I'm fairly certain you would have found the problem yourself as well.

CodePudding user response:

Python's itertools module has a nice pattern called grouper which you can use to split strings like this;

import itertools as it

def word_wrap(text, width):
    iters = [iter(text.replace(' ','-'))] * width
    return '\n'.join(''.join(chunk) for chunk in it.zip_longest(*iters, fillvalue=''))
  • Related