metaphas3
metaphas3

Reputation: 11

Checking pairs in a list?

Basically I have a program which will take a number and factor it down to the smallest number, being 2, 3, 5, 7, and so on. I'm having trouble figuring out how to check if there are one or multiple pairs of numbers inside of a list. For example.

    myList = [1,1,1,4,5,6,6,3,3,1]

in myList, there are four 1's which would be two pairs of two. Pairs then need to be thrown into another list but instead of adding both numbers making it a pair it only needs to have one of those numbers of the pair.

For example:

    myList = [1,1,1,4,5,6,6,3,3,1]
    doubles = [1,1,6,3]

So, there are four ones. Which in turn make two pairs of two, which would add into a list, but only one number needs to be added to a list representing a pair.

Upvotes: 1

Views: 9345

Answers (5)

Mykola Zotko
Mykola Zotko

Reputation: 17824

Another option with Counter:

from collections import Counter

myList = [1,1,1,4,5,6,6,3,3,1]

dupes = Counter({k: v // 2 for k, v in Counter(myList).items()})
sorted(dupes.elements())
# [1, 1, 3, 6]

Upvotes: 0

sahasrara62
sahasrara62

Reputation: 11228

using defaultdictionary

from collections import defaultdict
def func(lis):
    dic = defaultdict(int)
    for i in lis:
        dic[i]+=1
    list1 =[]
    for k,v in dic.items():
        if v>=2:
            list1.append([k]*(v//2))
    return list1    
myList = [1,1,1,4,5,6,6,3,3,1]
data =   [j for i in func(myList) for j in i]
print(data)
# output 
# [1,1,6,3]

Upvotes: 0

PM 2Ring
PM 2Ring

Reputation: 55479

This is similar to qarma's first solution, but it avoids the double for loop.

from collections import Counter

my_list = [1, 1, 1, 4, 5, 6, 6, 3, 3, 1, 7, 7, 7]
doubles = []
for k, v in Counter(my_list).items():
    doubles.extend([k] * (v // 2))

print(doubles)

output

[1, 1, 6, 3, 7]

Upvotes: 2

Dima Tisnek
Dima Tisnek

Reputation: 11781

simple solution

[k for k, v in collections.Counter([1,1,1,4,5,6,6,3,3,1]).items() for _i in range(v // 2)]
[1, 1, 3, 6]

Counter is a kind of a dict, thus doesn't keep insertion order. Also, it compresses input, so for example, input like 1, 1, 3, 3, 1, 1 is guaranteed to result in either 1, 1, 3 or 3, 1, 1 and never 1, 3, 1.

more complex

In [7]: def pairs(s):
   ...:     queue = set()
   ...:     for i in s:
   ...:         if i in queue:
   ...:             yield i
   ...:             queue.remove(i)
   ...:         else:
   ...:             queue.add(i)
   ...:

In [8]: list(pairs([1,1,1,4,5,6,6,3,3,1]))
Out[8]: [1, 6, 3, 1]

This, preserves order of pairs, but pairs are ordered according to last item in a pair, e.g. 1, 9, 9, 1 becomes 9, 1.

even more complex

In [12]: def pairs(s):
    ...:     incomplete = dict()
    ...:     done = []
    ...:     for i, v in enumerate(s):
    ...:         if v in incomplete:
    ...:             done.append((incomplete[v], v))
    ...:             del incomplete[v]
    ...:         else:
    ...:             incomplete[v] = i
    ...:     return [v[1] for v in sorted(done)]
    ...:
    ...:

In [13]: pairs([1,1,1,4,5,6,6,3,3,1])
Out[13]: [1, 1, 6, 3]

Here, original position of first element of each pair is kept as a value in the incomplete dict, which allows to reconstruct original order according to first item in a pair.

Upvotes: 1

shad0w_wa1k3r
shad0w_wa1k3r

Reputation: 13372

Something like this?

>>> myList = [1,1,1,4,5,6,6,3,3,1]
>>> mySet = set()
>>> doubles = []
>>> for i in myList:
...     if i in mySet:
...         doubles.append(i)
...         mySet.remove(i)
...     else:
...         mySet.add(i)
... 
>>> doubles
[1, 6, 3, 1]

Note - This doesn't preserve the order you seem to have expected in your question, i.e. [1, 1, 6, 3].

Upvotes: 1

Related Questions