2

Hello to Masters of Python!

As the title says, I have to concatenate substrings with the information provided in two lists of start and end position, respectively.

For example,

string     = 'AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJKKKK'
start_list = [0,8,16,24]
end_list   = [4,12,20,28]

The end result should be like

print (string[0:4]+string[8:12]+string[16:20]+string[24:28])

AAAACCCCEEEEGGGG

if the start and end positions increase, I have to do it with for loop iterating start and end positions of each elements in the two lists.

Could you please help me go through this?

Thank you in advance.

Kijewski
  • 25,517
  • 12
  • 101
  • 143
Karyo
  • 372
  • 2
  • 4
  • 21

5 Answers5

3

You can use zip:

''.join(string[a:b] for a, b in zip(start_list, end_list))

zip combines multiple iterators:

print zip(start_list, end_list)
> [(0, 4), (8, 12), (16, 20), (24, 28)]

If the list of indexes is long, you might want to use izip. See: When is it better to use zip instead of izip?

Community
  • 1
  • 1
Kijewski
  • 25,517
  • 12
  • 101
  • 143
2

You could use reduce and zip to do this:

In [1]: timeit reduce(lambda s, (i, j): s + string[i:j], zip(start_list, end_list), '')
100000 loops, best of 3: 2.67 μs per loop

This iterates through each (start, stop) pair of indices, and concatenates the substring of string given by those indices together.

Similarly, you could use a list comprehension or a generator and join:

In [3]: # generator
In [4]: timeit ''.join( string[i:j] for i, j in zip(start_list, end_list) )
100000 loops, best of 3: 3.43 μs per loop
In [5]: # list comprehension
In [6]: timeit ''.join([ string[i:j] for i, j in zip(start_list, end_list) ])
100000 loops, best of 3: 1.86 μs per loop

Finally, you could use @gnibbler's answer that uses string slicing:

In [7]: #slicing
In [8]: timeit ''.join(map(string.__getslice__, start_list, end_list))
100000 loops, best of 3: 1.82 μs per loop

Using timeit, the fastest way appears to be to using list slicing and join, followed by join and a list comprehension, and then reduce.

mdml
  • 22,442
  • 8
  • 58
  • 66
2
>>> ''.join(map(string.__getslice__, start_list, end_list))
'AAAACCCCEEEEGGGG'
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
0

Using List Comprehensions and str.join, you can easily achieve this:

''.join([string[v:end_list[i]] for i, v in enumerate(start_list)])

Or, you can just use the built-in zip() function:

''.join([string[start:end] for start, end in zip(start_list, end_list)])

Demo - List Comprehension:

>>> a =''.join([string[v:end_list[i]] for i, v in enumerate(start_list)])
>>> print(a)
AAAACCCCEEEEGGGG

Using zip():

>>> a = ''.join([string[start:end] for start, end in zip(start_list, end_list)])
>>> print(a)
AAAACCCCEEEEGGGG

Hope this helps!

aIKid
  • 26,968
  • 4
  • 39
  • 65
0

Apart from the answers already provided, you can also do:

''.join(map(lambda a,b: string[a:b], start_list, end_list))
dparpyani
  • 2,473
  • 2
  • 14
  • 16