-2

The list_1 have repeated values that are repeated in list_2 I need to find the elements that match from list_1 and list_2 and save them in result_list_1 and result_list_2 respectively and also the ones that do not match and save them in not_equals_list_1 and not_equals_list_2. The result of the items that match must also match in position.

Note: I need to use only arrays and not sets.

list_1 = [1, 5, 2, 3, 2, 4, 1, 3]
list_2 = [1, 2, 2, 3, 1, 6]

It should result in:

result_list_1 = [1, 2, 3, 2, 1]
result_list_2 = [1, 2, 3, 2, 1]

not_equals_list_1 = [3, 4, 5]
not_equals_list_2 = [6]

Your help would be of great help to me.

  • 2
    Have you tried anything yet? Where are you stuck exactly? I don't think I understand the spec, in any case -- where did the trailing `2, 1` sublist come from? These don't match on position or value. `not_equals_list_1` also appears sorted although that's not in the spec. – ggorlen Aug 10 '21 at 17:07
  • Is your `result_list_2` correct? Apparenty, `3` and `2` are swapped, or am I incorrect? – Captain Trojan Aug 10 '21 at 17:07
  • 1
    Does this answer your question? [How can I compare two lists in python and return matches](https://stackoverflow.com/questions/1388818/how-can-i-compare-two-lists-in-python-and-return-matches) – Adam G. Aug 10 '21 at 17:07
  • 2
    @AdamG. That answer will not work for the above since sets don't allow duplicates and the lists can be unequal length. – BTables Aug 10 '21 at 17:09
  • @Captain Trojan The order doesn't matter, I just need the "result_list_1" and "result_list_2" elements to match the position. –  Aug 10 '21 at 17:11
  • @ggorlen I have problems with duplicates, I always find the first one that matches and not the rest –  Aug 10 '21 at 17:15
  • @DayanaRodriguez Please share your code as an edit to your post. – ggorlen Aug 10 '21 at 17:18
  • 1
    @DayanaRodriguez Sorry, the order does not matter, but their positions matter? That makes no sense to me. Or are you saying that you just need those two lists to be equal? If that's the case, why do you need both? – Captain Trojan Aug 10 '21 at 17:19
  • Also, what would be the `result_1` and `result_2` for `list_1=[0, 1]` and `list_2=[1, 0]`? – Captain Trojan Aug 10 '21 at 17:24
  • @Capitán Trojan Yes, for example: result_list_1 [0] = 1; result_list_2 [0] = 1 or it could also be: result_list_1 [3] = 1 and result_list_2 [3] = 1 –  Aug 10 '21 at 17:24
  • @Capitán Trojan 'result_list_1' is for 'list_1' and 'result_list_2' is for 'list_2' –  Aug 10 '21 at 17:26
  • @DayanaRodriguez Which one of my question did you just answer `yes` to? Can you please explicitly explain how is `result_list_1` different from `result_list_2`? – Captain Trojan Aug 10 '21 at 17:27
  • @ggorlen `result_list_1` is for storing the matches of `list_1` and `result_list_2` is for the matches of `list_2`. I need the matches of both lists separated because this is a reproducible minimum, actually each item of `list_1` and `list_2` is an array, that is, I have an array of arrays. –  Aug 10 '21 at 17:37
  • 1
    It's not reproducible because you haven't shown your code that attempts to solve the problem, so the question is off topic. I get that you want different lists as output but I don't understand the logic for _how_ you came to get them (i.e. the specification). `result_list_1 = [1, 2, 3, 2, 1]` -- where did the last `2, 1` come from? If you have two identical lists as output, this seems redundant at the very least. All of the existing answers seem like random guesses as to your intent. – ggorlen Aug 10 '21 at 17:40
  • @ggorlen Sorry, the example of the values of list_1 and list_2 are the ones that I have simplified, actually I use an array of arrays and not a simple array. This is why I need the matches of list_1 and list_2 in different arrays. –  Aug 10 '21 at 18:45

4 Answers4

1

collections.Counter is invaluable for things like this - like a set but with multiplicity. The algorithm is simple - we make a Counter for each list, and then for the opposite list we just check whether each element is in the other list's counter. If so, remove one occurrence and put it in the result_list. Otherwise, put it in the not_equals_list.

from collections import Counter

list_1 = [1, 5, 2, 3, 2, 4, 1, 3]
list_2 = [1, 2, 2, 3, 1, 6]

counter_1 = Counter(list_1)
counter_2 = Counter(list_2)

result_list_1 = []
result_list_2 = []
not_equals_list_1 = []
not_equals_list_2 = []

for item in list_1:
    if counter_2[item] > 0:
        result_list_1.append(item)
        counter_2[item] -= 1
    else:
        not_equals_list_1.append(item)

for item in list_2:
    if counter_1[item] > 0:
        result_list_2.append(item)
        counter_1[item] -= 1
    else:
        not_equals_list_2.append(item)

print(result_list_1)  # [1, 2, 3, 2, 1]
print(result_list_2)  # [1, 2, 2, 3, 1]
print(not_equals_list_1) # [5, 4, 3]
print(not_equals_list_2) # [6]

Order is preserved in not_equals_list from the order of the first list. If you desire it differently, you can use reversed() where necessary to change either order of iteration or to simply flip the result.

If using this type of solution with custom objects, you'll need to make sure that __hash__() is properly implemented for equality checking - since both sets and dicts are hashtable-based, and Counter is just a subclass of dict.


From a quick google search, multiset might provide a more efficient way of doing this by just converting your lists into sets and then doing set operations on them. I haven't tested this, though.

Green Cloak Guy
  • 23,793
  • 4
  • 33
  • 53
1

My method would decrease your time complexity at the cost of space complexity.

def taketwoarray(arr1,arr2):
my_dict={}
for i in arr1:# add all arr1 elements to dict
    my_dict[i]=0
for i in arr2:# match if they are in arr1 increase count else set to -1
    try:
        if my_dict[i]!=-1:
            my_dict[i]+=1
    except:
        my_dict[i]=-1
#now you have count of numbers that came in both lists and the numbers themselves
#and the numbers that dont match in either would be marked by zero and -1 count.
# count is set to -1 to avoid numbers coming again and again only in arr2.

Let me know if there is any issue!

Ritik Attri
  • 109
  • 1
  • 2
0
result_list_1 = []
result_list_2 = []
not_equals_list_1 = []
not_equals_list_2 = []

for item in list_1:
    if item in list_2:
        result_list_1.append(item)
    else:
        not_equals_list_1.append(item)

for item in list_2:
    if item in list_1:
        result_list_2.append(item)
    else:
        not_equals_list_2.append(item)
Amin
  • 2,605
  • 2
  • 7
  • 15
-1
from collections import Counter

list_1 = [1, 5, 2, 3, 2, 4, 1, 3]
list_2 = [1, 2, 2, 3, 1, 6]

c1 = Counter(list_1)
c2 = Counter(list_2)

result_list_1 = [*(c1 & c2).elements()]
result_list_2 = result_list_1[:]
not_equals_list_1 = [*(c1 - c2).elements()]
not_equals_list_2 = [*(c2 - c1).elements()]

print(result_list_1)      # [1, 1, 2, 2, 3]
print(result_list_2)      # [1, 1, 2, 2, 3]
print(not_equals_list_1)  # [5, 3, 4]
print(not_equals_list_2)  # [6]
Kelly Bundy
  • 23,480
  • 7
  • 29
  • 65
  • Thank you very much for your answer, is there any way to do it without Counter comparing one by one? Also `result_list_2` must not be a copy of `result_list_1`. –  Aug 10 '21 at 18:30
  • 1
    @DayanaRodriguez Why and why? – Kelly Bundy Aug 10 '21 at 19:45