Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternative to Double Iteration

I have a procedure which requires me to check each value in a List against every other value in the same List. If I identify something that meets some requirement, I add it to another List to be removed after this procedure is finished.

Pseudo-code:

for value1 in my_list:
    for value2 in my_list:
        if meets_requirements(value1, value2):
            to_be_removed.append(value2)

This looks ugly to me. Naming conventions for the variables are difficult to assign or understand. There's the potential (although very un-likely, in this case) I could accidentally modify the list while iterating it. There may be issues with performance.

Is there a better alternative to performing these double iterations?

If not, are there any ways I can make this more readable and "feel" like quality code?

like image 944
Kurtis Avatar asked Dec 01 '13 21:12

Kurtis


3 Answers

You don't have to find the removed values first. Just create the list you need in one shot:

my_list = [y for y in my_list 
             if not any(meets_requirement(x,y) for x in my_list)]
like image 114
bcorso Avatar answered Oct 24 '22 03:10

bcorso


You can use itertools.product here. Though this is still equivalent to nested loops, but much more readable:

from itertools import product
for value1, value2 in product(my_list, repeat=2):
    if meets_requirements(value1, value2):
        to_be_removed.append(value2)
like image 4
Ashwini Chaudhary Avatar answered Oct 24 '22 03:10

Ashwini Chaudhary


I would have used a list comprehension together with product() from the itertools module:

from itertools import product
to_be_removed = [v2 for v1, v2 in product(mylist, repeat=2) 
                               if meets_requirement(v1, v2)]

Following @tobias_k's comment, if you don't want multiple instances of the same values in your result, and if the order of the elements doesn't matter, you can use a set comprehension instead:

to_be_removed = {v2 for v1, v2 in product(mylist, repeat=2) 
                               if meets_requirement(v1, v2)}
like image 2
Tim Pietzcker Avatar answered Oct 24 '22 03:10

Tim Pietzcker