def _combine_similar_molecules(molecules_list):
 new_guys_start_idx = 0
 while (new_guys_start_idx < len(molecules_list)):
  combined = ([False] * len(molecules_list))
  new_guys = []
  for j in xrange(new_guys_start_idx, len(molecules_list)):
   for i in xrange(0, j):
    if combined[i]:
     continue
    ((g1, m1), (g2, m2)) = (molecules_list[i], molecules_list[j])
    js = _jaccard_similarity(g1, g2)
    if (js > JACCARD_THRESHOLD):
     new_guys.append((g1.union(g2), m1.union(m2)))
     (combined[i], combined[j]) = (True, True)
     break
  molecules_list = [molecule for (molecule, was_combined) in zip(molecules_list, combined) if (not was_combined)]
  new_guys_start_idx = len(molecules_list)
  molecules_list.extend(new_guys)
 return molecules_list

def _combine_similar_molecules ( molecules_list ) : new_guys_start_idx = 0 while ( new_guys_start_idx < len ( molecules_list ) ) : combined = ( [ False ] * len ( molecules_list ) ) new_guys = [ ] for j in xrange ( new_guys_start_idx , len ( molecules_list ) ) : for i in xrange ( 0 , j ) : if combined [ i ] : continue ( ( g1 , m1 ) , ( g2 , m2 ) ) = ( molecules_list [ i ] , molecules_list [ j ] ) js = _jaccard_similarity ( g1 , g2 ) if ( js > JACCARD_THRESHOLD ) : new_guys . append ( ( g1 . union ( g2 ) , m1 . union ( m2 ) ) ) ( combined [ i ] , combined [ j ] ) = ( True , True ) break molecules_list = [ molecule for ( molecule , was_combined ) in zip ( molecules_list , combined ) if ( not was_combined ) ] new_guys_start_idx = len ( molecules_list ) molecules_list . extend ( new_guys ) return molecules_list
using a greedy approach here for speed .