Bob
Bob

Reputation: 1497

Compare values of two arrays in python

How can i check if item in b is in a and the found match item in a should not be use in the next matching?

Currently this code will match both 2 in b.

a = [3,2,5,4]
b = [2,4,2]

for i in b:
  if i in a:
    print "%d is in a" % i

This is the required output:

2 => 2 is in a
4 => 4 is in a
2 =>

EDIT: Example 2:

a = [3,2,2,4]
b = [2,4,2]

output should be

2 => 2 is in a
4 => 4 is in a
2 => 2 is in a

Upvotes: 6

Views: 31139

Answers (5)

elssar
elssar

Reputation: 5861

This probably isn't the best way to do it, but you could make a list of all matched items and check using that.

a= [3, 2, 5, 4]
b= [2, 4, 2]
c= []

for i in b:
    if i in a and i not in c:
        print '%d is in a' % i
        c.append(i)

I think looping over a instead of b should solve the problem.

a= [3, 2, 2, 4]
b= [2, 4, 2]

for i in a:
    if i in b:
        print i, 'is in a'

Obviously i is in a, but it does solve the problem doesn't it?

Upvotes: 0

Mihai Maruseac
Mihai Maruseac

Reputation: 21435

(long post but read it entirely, solution is at the end).

Remove the found value or register it in another dict.

Better though is to count the number of apparitions inside each array and test how many are common.

For the second case, you'd have

  • for a:

    3 appears 1 times 2 appears 1 times 5 appears 1 times 4 appears 1 times

  • for b:

    2 appears 2 times 4 appears 1 times

Keep these values in dictionaries:

a_app = {3:1, 2:1, 5:1, 4:1}
b_app = {2:2, 4:1}

And now, it is simple:

for i in b:
    if a_app.has_key(i) and a_app[i] > 0:
        a_app[i] -= 1

The b_app dictionary would be used in other case.

Here is a test script I wrote (testing all testcases issued here):

def f(a, b):
    a_app = {}
    for i in a:
        if not a_app.has_key(i):
            a_app[i] = 0
        a_app[i] += 1
    print a_app
    for i in b:
        print i, '=>',
        if a_app.has_key(i) and a_app[i] > 0:
            a_app[i] -= 1
            print i, ' is in a',
        print '.'

f([1,1,2],[1,1])
f([3,2,5,4],[2,4,2])
f([3,2,2,4],[2,4,2])
f([3,2,5,4],[2,3,2])

And here is the output:

$ python 1.py
{1: 2, 2: 1}
1 => 1  is in a .
1 => 1  is in a .
{2: 1, 3: 1, 4: 1, 5: 1}
2 => 2  is in a .
4 => 4  is in a .
2 => .
{2: 2, 3: 1, 4: 1}
2 => 2  is in a .
4 => 4  is in a .
2 => 2  is in a .
{2: 1, 3: 1, 4: 1, 5: 1}
2 => 2  is in a .
3 => 3  is in a .
2 => .

Everything is perfect and no order is lost :)

Edit: Updated with @Avaris's suggestions, this script looks like:

import collections

def f(a, b):
    a_app = collections.Counter(a)
    for i in b:
        print i, '=>',
        if i in a_app and a_app[i] > 0:
            a_app[i] -= 1
            print i, ' is in a',
        print '.'
    print ''

f([1,1,2],[1,1])
f([3,2,5,4],[2,4,2])
f([3,2,2,4],[2,4,2])
f([3,2,5,4],[2,3,2])

Upvotes: 11

Maria Zverina
Maria Zverina

Reputation: 11163

Recursive solution:

a = [3,2,5,4]
b = [2,4,2]

def find_matches(x, y):
    if y == []:            # nothing more to find
        return
    n = y.pop()
    if n in x:
        print n, "matches"
        x.remove(n)
    find_matches(x, y)

find_matches(list(a), list(b))      # copy the list as they get consumed in process

Upvotes: 3

Tim Pietzcker
Tim Pietzcker

Reputation: 336128

I would do this:

a = [3,2,5,4]
b = [2,4,2]
temp = set(a)
for item in b:
    if item in temp:
        print "{0} is in a".format(item)
        temp.remove(item)

The set makes the x in y check faster (O(1) instead of (worst-case) O(n)), and it also can be modified safely without destroying my original a.

Upvotes: 3

user434817
user434817

Reputation:

a = [3,2,5,4]
b = [2,4,2]

hadAlready = {}
for i in b:
    if i in a:
        if not (i in hadAlready):
            print "%d is in a" % i
            hadAlready[i] = 1

Upvotes: 0

Related Questions