Reputation: 11
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
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
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
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
Reputation: 11781
[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
.
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
.
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
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