Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iterating over a growing set in python

I have a set, setOfManyElements, which contains n elements. I need to go through all those elements and run a function on each element of S:

for s in setOfManyElements:
   elementsFound=EvilFunction(s)
   setOfManyElements|=elementsFound

EvilFunction(s) returns the set of elements it has found. Some of them will already be in S, some will be new, and some will be in S and will have already been tested.

The problem is that each time I run EvilFunction, S will expand (until a maximum set, at which point it will stop growing). So I am essentially iterating over a growing set. Also EvilFunction takes a long time to compute, so you do not want to run it twice on the same data.

Is there an efficient way to approach this problem in Python 2.7?

LATE EDIT: changed the name of the variables to make them more understandable. Thanks for the suggestion

like image 873
Pietro Speroni Avatar asked Feb 18 '15 13:02

Pietro Speroni


People also ask

Can you iterate over a set in Python?

In Python, Set is an unordered collection of data type that is iterable, mutable and has no duplicate elements. There are numerous ways that can be used to iterate over a Set.

Can you iterate over a set?

There is no way to iterate over a set without an iterator, apart from accessing the underlying structure that holds the data through reflection, and replicating the code provided by Set#iterator...

How do you iterate over an array of objects in Python?

Iterate through array itemslength tells our for loop to continue as long as i is less than the array's length (in this case, 7). i++ is equivalent to i+1 and means we're incrementing through our array by one each time. We could also use i+2 to proceed with every other item in the array, for example.

How do you iterate over a class in Python?

To create an object/class as an iterator you have to implement the methods __iter__() and __next__() to your object. As you have learned in the Python Classes/Objects chapter, all classes have a function called __init__() , which allows you to do some initializing when the object is being created.


2 Answers

I suggest an incremental version of 6502's approach:

seen   = set(initial_items)
active = set(initial_items)

while active:
    next_active = set()
    for item in active:
        for result in evil_func(item):
            if result not in seen:
                seen.add(result)
                next_active.add(result)
    active = next_active

This visits each item only once, and when finished seen contains all visited items.

For further research: this is a breadth-first graph search.

like image 168
Hugh Bothwell Avatar answered Oct 20 '22 10:10

Hugh Bothwell


You can just keep a set of already visited elements and pick a non-yet-visited element each time

visited = set()
todo = S
while todo:
    s = todo.pop()
    visited.add(s)
    todo |= EvilFunction(s) - visited
like image 31
6502 Avatar answered Oct 20 '22 09:10

6502