modifying a list while iterating through

D

dustin.getz

consider the following working loop where Packet is a subclass of
list, with Packet.insert(index, iterable) inserting each item in
iterable into Packet at consecutive indexes starting at index.

i=0
while(i<len(packet)-4):
if packet[i:i+5]==Packet("01110"):
packet.insert(i, "01111")
i+=10 #skip the 5 bits inserted, and skip the 5 bits just
checked bc overlap should not trigger insertion
else: i+=1

is there a way to do this more elegantly? seems like a big kludge.
 
G

George Sakkis

consider the following working loop where Packet is a subclass of
list, with Packet.insert(index, iterable) inserting each item in
iterable into Packet at consecutive indexes starting at index.

i=0
while(i<len(packet)-4):
if packet[i:i+5]==Packet("01110"):
packet.insert(i, "01111")
i+=10 #skip the 5 bits inserted, and skip the 5 bits just
checked bc overlap should not trigger insertion
else: i+=1

is there a way to do this more elegantly? seems like a big kludge.

Unless I missed something, this is a simple string replacement:

''.join(packet).replace('01110', '0111001111')


George
 
A

attn.steven.kuo

consider the following working loop where Packet is a subclass of
list, with Packet.insert(index, iterable) inserting each item in
iterable into Packet at consecutive indexes starting at index.

i=0
while(i<len(packet)-4):
if packet[i:i+5]==Packet("01110"):
packet.insert(i, "01111")
i+=10 #skip the 5 bits inserted, and skip the 5 bits just
checked bc overlap should not trigger insertion
else: i+=1

is there a way to do this more elegantly? seems like a big kludge.


If Packet consists of '0's and '1's, then it may be
easier to convert to, or base the class on str (strings):

packet = "1010101111011100111010001"
print "BEFORE ", packet
li = packet.split("01110")
packet = "0111001111".join(li)
print "AFTER ", packet
 
D

dustin.getz

consider the following working loop where Packet is a subclass of
list, with Packet.insert(index, iterable) inserting each item in
iterable into Packet at consecutive indexes starting at index.
i=0
while(i<len(packet)-4):
if packet[i:i+5]==Packet("01110"):
packet.insert(i, "01111")
i+=10 #skip the 5 bits inserted, and skip the 5 bits just
checked bc overlap should not trigger insertion
else: i+=1
is there a way to do this more elegantly? seems like a big kludge.

If Packet consists of '0's and '1's, then it may be
easier to convert to, or base the class on str (strings):

packet = "1010101111011100111010001"
print "BEFORE ", packet
li = packet.split("01110")
packet = "0111001111".join(li)
print "AFTER ", packet



Steven, George,

Thanks for your responses. Yea, that would work.

My original question still stands, though, in situations where a
simple string replacement might not be sufficient. Is there a way to
insert into a list whilst iterating through it?

for example, consider a list of binary values.

for index in range(len(iterable)):
item=iterable[index]
if item==1:
iterable.insert(index,0)

obv this wouldn't work because now all future indexes will be off by
the number of previously inserted items.

using a while loop to fix this ugly and counterintuitive.
 
S

Steven D'Aprano

My original question still stands, though, in situations where a
simple string replacement might not be sufficient. Is there a way to
insert into a list whilst iterating through it?

Inserting/deleting from a list while you're walking through it is *always*
tricky, by its very nature.

Deletions are easy to deal with: iterate over the list backwards. When
you delete the current item, the only items that are re-numbered are items
you've already looked at.

Similarly, if you iterate backwards over the list and make sure you only
insert after the current item, never before, you can avoid re-numbering
items you haven't looked at yet.

Another solution is to iterate over the list, creating a new list as you
go:

new = []
for item in some_list:
if condition:
# delete the item
pass
elif other_condition:
# insert something
new.extend(['something', item])
else:
new.append(item)




for example, consider a list of binary values.

for index in range(len(iterable)):
item=iterable[index]

The Pythonic way to write that is

for index,item in enumerate(iterable):
pass

if item==1:
iterable.insert(index,0)

"Iterables" are sequences and iterators -- anything you can iterate over.
In general, only sequences can be inserted into (and not even all
sequences).

obv this wouldn't work because now all future indexes will be off by the
number of previously inserted items.

using a while loop to fix this ugly and counterintuitive.

Well, if you insist on doing a tricky job, you're always going to have
tricky code. Here's one solution:

# inserting into a mutable sequence
sequence.reverse()
for index in range(len(sequence)-1, -1, -1):
item = sequence[index]
if item == 1:
sequence.insert(index+1, 0)
sequence.reverse()


Here's a solution that should work for any iterable, provided you have
sufficient memory:

# inserting into a copy of iterable
copy = []
for item in iterable:
if item == 1:
copy.append(0)
copy.append(item)


Hope this helps.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,740
Latest member
AdolphBig6

Latest Threads

Top