Terence Chow
Terence Chow

Reputation: 11153

using FOR statement on 2 elements at once python

I have the following list of variables and a mastervariable

a = (1,5,7)

b = (1,3,5)

c = (2,2,2)

d = (5,2,8)

e = (5,5,8)

mastervariable = (3,2,5)

I'm trying to check if 2 elements in each variable exist in the master variable, such that the above would show B (3,5) and D (5,2) as being elements with at least 2 elements matching in the mastervariable. Also note that using sets would result in C showing up as matchign but I don't want to count C cause only 'one' of the elements in C are in mastervariable (i.e. 2 only shows up once in mastervariable not twice)

I currently have the very inefficient:

if current_variable[0]==mastervariable[0]:
            if current_variable[1] = mastervariable[1]:
                        True                        
            elif current_variable[2] = mastervariable[1]:
                        True       

  #### I don't use OR here because I need to know which variables match.

elif current_variable[1] == mastervariable[0]:   ##<-- I'm now checking 2nd element
            etc. etc.

I then continue to iterate like the above by checking each one at a time which is extremely inefficient. I did the above because using a FOR statement resulted in me checking the first element twice which was incorrect:

For i in a:
      for j in a:
           ### this checked if 1 was in the master variable and not 1,5 or 1,7

Is there a way to use 2 FOR statement that allows me to check 2 elements in a list at once while skipping any element that has been used already? Alternatively, can you suggest an efficient way to do what I'm trying?

Edit: Mastervariable can have duplicates in it.

Upvotes: 0

Views: 99

Answers (2)

John La Rooy
John La Rooy

Reputation: 304137

Seems like a good job for sets. Edit: sets aren't suitable since mastervariable can contain duplicates. Here is a version using Counters.

>>> a = (1,5,7)
>>> 
>>> b = (1,3,5)
>>> 
>>> c = (2,2,2)
>>> 
>>> d = (5,2,8)
>>> 
>>> e = (5,5,8)
>>> D=dict(a=a, b=b, c=c, d=d, e=e)
>>> 
>>> from collections import Counter
>>> mastervariable = (5,5,3)
>>> mvc = Counter(mastervariable)
>>> for k,v in D.items():
...  vc = Counter(v)
...  if sum(min(count, vc[item]) for item, count in mvc.items())==2:
...   print k
... 
b
e

Upvotes: 1

lvc
lvc

Reputation: 35059

For the case where matching elements can be duplicated so that set breaks, use Counter as a multiset - the duplicates between a and master are found by:

count_a = Counter(a)
count_master = Counter(master)
count_both = count_a + count_master
dups = Counter({e : min((count_a[e], count_master[e])) for e in count_a if count_both[e] > count_a[e]})

The logic is reasonably intuitive: if there's more of an item in the combined count of a and master, then it is duplicated, and the multiplicity is however many of that item are in whichever of a and master has less of them.

It gives a Counter of all the duplicates, where the count is their multiplicity. If you want it back as a tuple, you can do tuple(dups.elements()):

>>> a
(2, 2, 2)
>>> master
(1, 2, 2)
>>> dups = Counter({e : min((count_a[e], count_master[e])) for e in count_a if count_both[e] > count_a[e]})
>>> tuple(dups.elements())
(2, 2)

Upvotes: 1

Related Questions