Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a for loop to do this in python

Tags:

python

I'm trying to use a for loop in order to formulate this:

  • expand('*+123456') should return '1*2+3*4+5*6'

  • expand('++123') should return '1+2+3'

  • expand('+*1234') should return '1+2*3+4'

A symbol is chosen from the first two characters of the given string in an alternating fashion and placed between the proceeding digits.

Here is what I've been working with:

def expand(original):
    var = ""
    symbols = original[0:2]
    for i in range(len(original)):
        var = var + symbols + original[i]
    return var

I realize that there also must be a original[2:] but I don't know where I can fit this into in here.

I'm an amateur and I've been trying to figure out this question for a long time.

like image 342
Flow Avatar asked Dec 20 '22 14:12

Flow


1 Answers

Yes, your function would be improved by adding [2:] in there, but it could also do with losing the range(len(original)). Whenever you find yourself writing range(len(something)), you should step back and think about what you're actually trying to do.

In this case, you're looking for the characters in the string, and you can get those more straightforwardly with for x in string. Here's a slightly improved version, taking those ideas into account:

def expand(original):
    var = ""
    symbols = original[:2]
    for digit in original[2:]:
        var += (digit + symbols)
    return var

This stops you from getting the weird mixture of symbols at the beginning of the output, but it's still not perfect:

>>> expand('+*1234')
'1+*2+*3+*4+*'

We need to find a way of

  1. taking the symbols alternately, and
  2. leaving them off the end of the string.

We can use itertools.cycle to handle the first of these, and string slicing for the second:

from itertools import cycle

def expand(original):
    var = ""
    symbols = cycle(original[:2])
    for digit in original[2:]:
        var += (digit + next(symbols))
    return var[:-1]

That works, but at some point, someone's going to pipe up and tell you you shouldn't use + or += to build strings, because it's inefficient. If we build a list instead, and then use str.join() to turn that into a string, we can improve things slightly:

from itertools import cycle

def expand(original):
    chars = []
    symbols = cycle(original[:2])
    for digit in original[2:]:
        chars.extend([digit, next(symbols)])
    return "".join(chars[:-1])

However, we can do better than that. Rather than having to call next(symbols) every time, we can use zip() to get the next symbol and next digit a pair at a time:

from itertools import cycle

def expand(original):
    chars = []
    for symbol, digit in zip(cycle(original[:2]), original[2:]):
        chars.extend([digit, symbol])
    return "".join(chars[:-1])

... and that's probably enough :-)

EDIT: Since in a comment to another answer, you've said you're not allowed to import anything from the standard library (a rather silly restriction IMO, but there it is), you can use the Python implementation of cycle() described at the link earlier in this answer:

def cycle(iterable):
    # cycle('ABCD') --> A B C D A B C D A B C D ...
    saved = []
    for element in iterable:
        yield element
        saved.append(element)
    while saved:
        for element in saved:
            yield element

... but you'll probably have to be prepared to convince your teacher that you understand it, which means you need to understand the yield keyword.

like image 111
Zero Piraeus Avatar answered Dec 29 '22 00:12

Zero Piraeus