Hemmelig
Hemmelig

Reputation: 794

String slicing by index list

I have a list of lengths present in a list, like:

a = [1, 3, 4]

Moreover, I have string who's length is exactly the sum of the numbers of a, here 8, looking like that:

s = "01100110"

I am looping over length of a and every time, I would like to have exactly the next n bits present in a. So here, it would be three runs, giving me "0", "110" and "0110".

Is there a very clever idea to do that efficient, for example by slicing? I have some weird complicated ways in my head but search for something more efficient.

Some solution I came up with:

counter_index = 0
counter_sum = 0

for i in range(len(a)):
   res = s[counter_sum:counter_sum+a[counter_index]
   counter_sum += a[counter_index]
   counter_index += 1
   print(res)

Upvotes: 4

Views: 832

Answers (5)

jmd_dk
jmd_dk

Reputation: 13120

I think the cleanest solution is to just loop over the indices in a directly, like so:

a = [1, 3, 4]
s = "01100110"
bgn = 0
for i in a:
    end = bgn + i
    # The wanted slice
    print(s[bgn:end])  # 0, 110, 0110
    # The next slice begins where this one left off
    bgn = end

If you need the results, you can pack them in a list:

a = [1, 3, 4]
s = "01100110"
results = []
bgn = 0
for i in a:
    end = bgn + i
    results.append(s[bgn:end])
    bgn = end
print(results)  # ['0', '110', '0110']

You could go for a list comprehension, but I think this would degrade the readability enough that it is not the right way to go.

Upvotes: 1

user2390182
user2390182

Reputation: 73498

You can turn the string into an iterator. Then you can simply keep consuming it in the given chunk sizes:

it = iter(s)
["".join(next(it) for _ in range(chunk)) for chunk in a]
# ['0', '110', '0110']

You could make this yet more concise with itertools.islice:

from itertools import islice

it = iter(s)
["".join(islice(it, chunk)) for chunk in a]
['0', '110', '0110']

Upvotes: 2

Steven Thomas
Steven Thomas

Reputation: 374

Edit as my initial response was wrong.

I = 0 # inital starting index
i = 0 # counter for len(a)
while i < len(a):
    J = sum(a[:i+1]) # second starting index
    print(s[I:J]) # or whatever function you need
    I = J # making starting index for next loop equal to this starting index
    i += 1 # increment counter
0
110
0110

Upvotes: 0

vnk
vnk

Reputation: 1082

This approach basically updates the string each time it is sliced so we can get the next value by simply using the values in a as the index value directly instead of adding it to the existing position value.

a = [1, 3, 4]
s = "01100110"
st = s
i = 0
while i < len(a):
    print(st[:a[i]])
    st = st[a[i]:]
    i+=1
 

Output

0
110
0110

Upvotes: 3

balderman
balderman

Reputation: 23825

something like the below is the "slicing" solution to go with

a = [1, 3, 4]
s = "01100110"
offset = 0
for x in a:
    print(f'{s[offset: offset+x]}')
    offset += x

output

0
110
0110

Upvotes: 2

Related Questions