3

I have a problem that I could not find a good answer for: I want to merge two lists but keep the same number of occurrences from each object EX:

list1 = [2,3,7]
list2 = [2,2,5]

After merging thees two lists the result should look like this:

res = [2,2,3,5,7] #it does not need to be sorted

Observe that from the beginning there was together three "2" but after merging there should only be two "2"

The closest I have found is in this post: Combining two lists and removing duplicates, without removing duplicates in original list

but this does not work the way I want it.

an other example:

l1 = [2]
l2 = [3]
l3 = [2,2]
l4 = [5]
l5 = [2,3]

#after adding all the lists above
result = [2,2,3,5]
Community
  • 1
  • 1
user966504
  • 63
  • 2
  • 1
    Why are there only two after merging? – Simeon Visser Oct 08 '13 at 11:46
  • 4
    Create a Counter for both lists and output max(counter1, counter2) items for each entry into a resulting list. – dornhege Oct 08 '13 at 11:48
  • well, merging might be the wrong word but it is like this: if we "merge" l1 and l2 we get [2,3]. If we then "merge" the new list with l3 we get [2,2,3] (only two 2) and so on... – user966504 Oct 08 '13 at 11:49
  • What happens when we merge `[2,3]` with `[2,2,2,2,3]`? – Simeon Visser Oct 08 '13 at 11:56
  • Are your original lists sorted? Do you care about algorithmic efficiency? dornherge's Counter solution should work, but wont be the most optimal if the original list is sorted. Shouldn't matter unless you have millions of elements. – Hari Menon Oct 08 '13 at 11:56

2 Answers2

9

As I understand your question, you want each number to appear in the result with the maximum frequency it appears in any of the input lists. You can use a collections.Counter to get the frequencies for each individual list, and use the | operator on them to merge them:

>>> c = collections.Counter([2, 2, 5])
>>> d = collections.Counter([2, 3, 7])
>>> list((c | d).elements())
[2, 2, 3, 5, 7]

Here's a function to join any number of lists:

def merge_max_frequency(*iterables):
    return reduce(operator.or_, map(collections.Counter, iterables)).elements()

This function returns an iterable rather than a list -- simply apply list() to it to get a list.

sloth
  • 99,095
  • 21
  • 171
  • 219
Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
0

It feels a bit overly complex, but this is how I would solve it:

>>> newlist = []
>>> for i,j in zip(list1, list2):
>>>    newlist.append(set([i,j]))
>>> [x for sub in newlist for x in sub]      # flattening the list of sets
[2, 2, 3, 5, 7]
sloth
  • 99,095
  • 21
  • 171
  • 219
PascalVKooten
  • 20,643
  • 17
  • 103
  • 160