0

So I'm given a list of tuples. Each tuple contains an integer, a string, and a boolean. I want to go through the list and find the first tuple that has a False for that boolean, do some operation with the tuple, then change the boolean to true. Here's some sample code:

def sendnext(packets):
    for (number, data, sent) in packets:
        if not sent:
            sendsegment(number, data)
            sent = True
            break

Obviously, I can't just change sent to True. The list can also grow arbitrarily large, so I don't want to make a copy of it or use a list comprehension. I know I could use indexing, but that will probably reduce readability. I feel like there should be a pythonic way to do this. Any suggestions?

Thanks for your help!

2
  • Do you need to preserve the packets later on? Or you just need to do the sendsegment if sent = False? Commented Nov 14, 2013 at 3:28
  • Yes, they'll be used later. Packets is actually a global list. Commented Nov 14, 2013 at 3:32

3 Answers 3

2

I would define a Packet class and then simply perform operations on each Packet object

# assuming a Packet class has been defined and you have a list of Packet objects
for packet in packets:
  if not packet.sent:
    sendsegment(packet.number, packet.data)
    packet.sent = true
    break

Especially since you'll be using the packets elsewhere, and presumably is a major component in your program, it might be easier and more manageable to avoid working with arbitrary lists of data.

Sign up to request clarification or add additional context in comments.

1 Comment

This is a great idea, but unfortunately I'm not able to change how the packets are defined.
1

Just use an index variable so that you're changing the actual values, instead of a copy:

def sendnext(packets):
    for i in range(len(packets)):
        if not packets[i][2]:
            sendsegment(packets[i][0], packets[i][1])
            packets[i] = (packets[i][0], packets[i][1], True)
            break

For simplicity, iteration can be done with enumerate:

def sendnext(packets):
    for i, (number, data, sent) in enumerate(packets):
        if not sent:
            sendsegment(number, data)
            packets[i] = (number, data, True)
            break

6 Comments

The second to last line would be packets[i] = (packets[i][0], packets[i][1], True). I think I'll end up using this, but that line just makes me uneasy.
This looks good, except it's briefer and less error-prone to use "for index, packet in enumerate(packets)" instead of range(len).
@Championcake Whoops, I always forget that tuple elements can't be assigned to (since tuples are immutable). I fixed the answer.
@dstromberg My preference is usually for indexing (perhapse due to being a C-style transplant), but that is, of course, briefer. I've included a more readable option including enumerate.
Note that tuple unpacking can be done in the for line, like so: for i, (number, data, sent) in enumerate(packets):. It's clearer that way, provided you're used to it ;-)
|
0

Can you use a generator approach here to map some computation on your iteration of packets? Something like:

def sendnext(packets):
    for (number, data, sent) in packets:
        if not sent:
            sendsegment(number, data)
            yield (number, data, True)
        else:
            yield (number, data, True)

where we relinquish control of packets to sendnext, and then just use the packets that get yielded by sendnext?

Comments

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.