Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python for loop list plus one item

Tags:

python

list

I'm handling mouse clicks on objects based on the location of the object on the screen. I record the xy coord of the mouse click and see if it matches any of the objects that are allowed to be clicked on. The objects are in different lists or just single objects, but I want them in one big list so I can just loop through the whole thing once, if the click is on one of the objects, do the work, break. You can only click on one object.

First method: how i'm doing it now:

list = [obj1, obj2, obj3]
singleobj

copylist = list
copylist.append(singleobj)

for item in copylist:
    if item.pos == mouseclick.pos:
        doWork(item)
        break

Second method: I'd rather do something like below, but obviously the list+singleobj is not valid:

for item in list+singleobj:
    if item.pos == mouseclick.pos:
        doWork(item)
        break

Third method: Or if I absolutely had to, I could do this horrible terrible code:

list = [obj1, obj2, obj3]

foundobj = None

for item in list:
    if item.pos == mouseclick.pos:
        foundobj = item
        break

if foundobj is None:
    if singleobj.pos == mouseclick.pos:
        foundobj = singleobj

#possibly repeated several times here....


if foundobj is not None:
    doWork(foundobj)

The first method seems slow because I have to copy all of the (possibly many) lists and single objects into one list.

The second method seems ideal because it's compact and easy to maintain. Although, as it stands now it's simply pseudo code.

The third method is bulky and clunky.

Which method should I use? If the second, can you give the actual code?

like image 298
jb. Avatar asked Dec 02 '11 08:12

jb.


2 Answers

For 2nd method you need itertools.chain

for item in itertools.chain(list, [singleobj]):
    ...
like image 171
DrTyrsa Avatar answered Sep 30 '22 19:09

DrTyrsa


DrTyrsa's answer is what I was about to say about your precise question, but let me give you a few other tips:

copylist = list
copylist.append(singleobj)

this does not create a copy of the list, you might want to do copylist = list[:] or copylist = list(lst) (I changed the name here to lst, because list is a builtin. you know).

about your second method, you can do:

for item in list + [singleobj]:
    ...

and if you are going to use itertools, a tiny improvement is to use a tuple rather than a list to hold the extra object, as it's a little bit more lightweight:

for item in itertools.chain(list, (singleobj,)):
    ...

the other thing is that you should not be looping your objects to see if the coordinates match, you can have them indexed by their boundaries (in something like a BSP tree or a Quadtree) and do a faster lookup.

like image 22
fortran Avatar answered Sep 30 '22 21:09

fortran