4

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)
2
  • 3
    can you share the current code you have ? Commented Sep 28, 2021 at 8:41
  • I added one I came up with :) Commented Sep 28, 2021 at 8:45

5 Answers 5

3

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
Sign up to request clarification or add additional context in comments.

4 Comments

This works for the OPs request, however I think you should consider ammending this to create a dummy variable instead of ammending the original string, in case that variable is needed later.
Thanks! I have edited the answer accordingly.
Nice ammendment. Perhaps a function taking in s and a would be the best approach. This depends if the person needs to do this many many times with many variables, as using a function shouldn't permanently make a new variable in memory. We're now going above and beyond the initial scope by quite a bit though.
That's a good point. We don't know the entire context of the question here though so I guess it's up to the OP to decide how to implement it.
2

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

Comments

2

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']

4 Comments

This is very elegant (+1), but unfortunately very inefficient. This is O(2 * i * len(a)) compared to O(len(a)) for @balderman's solution.
No, it's not. It's just as linear as the slices. Also, O(2* i * len(a)) == O(len(s)). And the actual asymptotic complexity of both approaches is O(len(s))!
Well, technically yes. But the running time is 5x slower for the example and even slower for larger slices.
@MichaelSzczesny Yeah, that's to be expected. String slices are super C-optimized. But the iterator pattern is good to know for such cases as you don't need to keep track of your position in the sequence. ANd it makes for concise and readable code.
1

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.

Comments

0

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

1 Comment

You're right, I misread the OPs outputs. Should I delete or ammend my answer?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.