1

I am working in Python 2.7. I am trying to create a function which can zip a string into a larger string starting at an arbitrary index and with an arbitrary step.

For example, I may want to zip the string @#*#* into the larger string TNAXHAXMKQWGZESEJFPYDMYP starting at the 5th character with a step of 3. The resulting string should be:

TNAXHAX@MK#QW*GZ#ES*EJFPYDMYP

The working function that I came up with is

#Insert one character of string every nth position starting after ith position of text

text="TNAXHAXMKQWGZESEJFPYDMYP"

def zip_in(string,text,i,n):
    text=list(text)
    for c in string:
        text.insert(i+n-1,c)
        i +=n
    text = ''.join(text)
    print text

This function produces the desired result, but I feel that it is not as elegant as it could be.

Further, I would like it to be general enough that I can zip in a string backwards, that is, starting at the ith position of the text, I would like to insert the string in one character at a time with a backwards step.

For example, I may want to zip the string @#*#* into the larger string TNAXHAXMKQWGZESEJFPYDMYP starting at the 22nd position with a step of -3. The resulting string should be:

TNAXHAXMKQW*GZ#ES*EJ#FP@YDMYP

With my current function, I can do this by setting n negative, but if I want a step of -3, I need to set n as -2.

All of this leads me to my question:

Is there a more elegant (or Pythonic) way to achieve my end?


Here are some related questions which don't provide a general answer:

Pythonic way to insert every 2 elements in a string
Insert element in Python list after every nth element
Merge Two strings Together at N & X

Community
  • 1
  • 1
DyingIsFun
  • 1,227
  • 2
  • 10
  • 21

1 Answers1

0

You can use some functions from the itertools and more_itertools libraries (make sure to have them) and combine them to get your result : chunked and izip_longest.

# Parameters
s1 = 'ABCDEFGHIJKLMNOPQ' # your string
s2 = '@#@#' # your string of elements to add
int_from = 4 # position from which we start adding letters
step = 2 # we will add in elements of s2 each 2 letters

return_list = list(s1)[:int_from] # keep the first int_from elements unchanged
for letter, char in izip_longest(chunked(list(s1)[int_from:], step), s2, fillvalue=''):
    return_list.extend(letter)
    return_list.append(char)

Then get your string back by doing :

''.join(return_list)

Output :

# For the parameters above the output is :
>> 'ABCDEF@GH#IJ@KL#MNOPQ'

What does izip_longest(chunked(list(s1)[int_from:], step), s2, fillvalue='') return ?:

for letter, char in izip_longest(chunked(list(s1)[int_from:], step), s2, fillvalue=''):
    print(letter, char)

>> Output
>> (['E', 'F'], '@')
   (['G', 'H'], '#')
   (['I', 'J'], '@')
   (['K', 'L'], '#')
   (['M', 'N'], '')
   (['O', 'P'], '')
   (['Q'], '')
MMF
  • 5,750
  • 3
  • 16
  • 20