简体   繁体   中英

Obtaining a list of ordered integers from a list of "pairs" in Python

Hello I am currently working with a large set of data which contains an even amount of integers, all of which have a matching value. I am trying to create a list which is made up of "one of a pair" in Python.I am able to have multiple pairs of the same value, thus simply using the set function does not work. For example, if I have a list:

List = [10, 10, 11, 20, 15, 20, 15, 11, 10, 10]

In this example, indices 0 and 1 would be a pair, then 2 and 7 , 3 and 5 , 4 and 6 , 8 and 9 .

I want to extract from that list the values that make up each pair and create a new list with said values to produce something such as:

newList = [10, 11, 20, 15, 10]

Using the set function makes it such that only one element from the entire set of data is put into the list, where I need half of the total data from List . For situations where I have more than one pair of the same value, it would look something such as:

List = [10, 10, 11, 10, 11, 10]

Would need to produce a list such as:

newList = [10, 11, 10]

Any insight would be great as I am new to Python and there are a lot of functions I may not be aware of.

Thank you

Just try:

new_list = set(list)

This should return your desired output.

If I've understood correctly, you don't want to have any duplicated value, want to retain a list with unique values from a particular list.

If I'm right, a simple way to do so would be:

List = [10, 10, 11, 11, 15, 20, 15, 20]
newList = []
for x in List:
    if x not in newList:
        newList.append(x)

print(newList)

A python-like way to do so would be:

newList = set(List)

Here is a slight variation on one of @Alain T's answer:

 [i for s in [set()] for i in List if (s.remove(i) if i in s else (not s.add(i)))] 

NB: the following was my answer before you add the ordering requirement

sorted(List)[::2]

This sorts the input List and then take only one value out of each two consecutive.

As a general approach, this'll do:

l = [10, 10, 11, 20, 15, 20, 15, 11, 10, 10]
i = 0
while i < len(l):
    del l[l.index(l[i], i + 1)]
    i += 1

It iterates through the list one by one, finding the index of the next occurrence of the current value, and deletes it, shortening the list. This can probably be dressed up in various ways, but is a simple algorithm. Should a number not have a matching pair, this will raise a ValueError .

The following code reates a new list of half the number of items occuring in the input list. The order is in the order of first occurrence in the input list.

>>> from collections import Counter
>>> d = [10, 10, 11, 20, 15, 20, 15, 11, 10, 10]
>>> c = Counter(d)
>>> c
Counter({10: 4, 11: 2, 20: 2, 15: 2})
>>> answer  = sum([[key] * (val // 2) for key, val in c.items()], [])
>>> answer
[10, 10, 11, 20, 15]
>>> 

If you need to preserve the order of the first occurrence of each pair, you could use a set with an XOR operation on values to alternate between first and second occurrences.

List = [10, 10, 11, 20, 15, 20, 15, 11, 10, 10]

paired = [ i for pairs in [set()] for i in List if pairs.symmetric_difference_update({i}) or i in pairs]
print(p)
# [10, 11, 20, 15, 10]

You could also do this with the accumulate function from itertools:

from itertools import accumulate
paired = [a for a,b in zip(List,accumulate(({n} for n in List),set.__xor__)) if a in b]
print(paired)
# [10, 11, 20, 15, 10]

Or use a bitmap instead of a set (if your values are relatively small positive integers (eg between 0 and 64):

paired = [ n for n,m in zip(List,accumulate((1<<n for n in List),int.__xor__)) if (1<<n)&m ]
print(paired)
# [10, 11, 20, 15, 10]

Or you could use a Counter from collections

from collections import Counter
paired = [ i for c in [Counter(List)] for i in List if c.update({i:-1}) or c[i]&1 ]
print(paired)
# [10, 11, 20, 15, 10]

And , if you're not too worried about efficiency, a double sort with a 2 step striding could do it:

paired = [List[i] for i,_ in sorted(sorted(enumerate(List),key=lambda n:n[1])[::2])]
print(paired)
# [10, 11, 20, 15, 10]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM