What is the best option to retrieve only non-duplicate elements from a Python list? Say I have the following list:
lst = [1, 2, 3, 2, 3, 4]
I would like to retrieve the following:
lst = [1, 4]
(2 and 3 are not unique in that list, so they don't get retrieved)
Use collections.Counter to get counts of items. Combine with a list comprehension to keep only those that have a count of one.
>>> from collections import Counter
>>> lst = [1, 2, 3, 2, 3, 4]
>>> [item for item, count in Counter(lst).items() if count == 1]
[1, 4]
This is a breeze with a list comprehension:
>>> lst = [1, 2, 3, 2, 3, 4]
>>> [x for x in lst if lst.count(x) == 1]
[1, 4]
>>>
Also, I recommend that you do not name a variable list--it overshadows the built-in.
Related
I have a list of list of integers:
ls = [[1,2,3],[2,2,3],[1,1,3]]
and I want to end up with a list that has len(ls[0]) elements, and each element is the element that appears most in that index. In this example the result would be [1 (appears in first&last), 2 (appears in first&second), 3 (appears in all)]
I tried using loops and was hoping for a built-in like all (most?)
ls = [[1,2,3],[2,2,3],[1,1,3]]
ls2=[]
ls2 =[item for sub in ls for item in sub]
ls2
Out[40]: [1, 2, 3, 2, 2, 3, 1, 1, 3]
ls3=[]
for item in len(ls):...
What would be the way to do so?
Transpose your list, apply Counters.
>>> from collections import Counter
>>> ls = [[1,2,3],[2,2,3],[1,1,3]]
>>> counts = [Counter(x) for x in zip(*ls)]
>>> [c.most_common(1)[0][0] for c in counts]
[1, 2, 3]
This will pick an arbitrary number if two numbers share the highest occurence for the same index.
my (alternative solution) 2 cents:
>>> ls = [[1, 2, 3], [2, 2, 3], [1, 1, 3]]
>>> l_mc = [max(x, key=x.count) for x in zip(*ls)]
>>> l_mc
[1, 2, 3]
Here is another way:
from collections import Counter
from operator import itemgetter
ls = [[1, 2, 3], [2, 2, 3], [1, 1, 3]]
print([max(x.items(), key = itemgetter(1))[0] for x in map(Counter, zip(*ls))])
# [1, 2, 3]
Newbie with a question, so please be gentle:
list = [1, 2, 3, 4, 5]
list2 = list
def fxn(list,list2):
for number in list:
print(number)
print(list)
list2.remove(number)
print("after remove list is ", list, " and list 2 is ", list2)
return list, list2
list, list2 = fxn(list, list2)
print("after fxn list is ", list)
print("after fxn list2 is ", list2)
This results in:
1
[1, 2, 3, 4, 5]
after remove list is [2, 3, 4, 5] and list 2 is [2, 3, 4, 5]
3
[2, 3, 4, 5]
after remove list is [2, 4, 5] and list 2 is [2, 4, 5]
5
[2, 4, 5]
after remove list is [2, 4] and list 2 is [2, 4]
after fxn list is [2, 4]
after fxn list2 is [2, 4]
I don't understand why list is changing when I am only doing list2.remove(), not list.remove(). I'm not even sure what search terms to use to figure it out.
The reason this is happening can be found here:
mlist = [1,2,3,4,5]
mlist2 = mlist
the second statement "points" mlist2 to mlist (i.e., they both refer to the same list object) and any changes you make to one is reflected in the other.
To make a copy instead try this (using a slice operation):
mlist = [1,2,3,4,5]
mlist2 = mlist[:]
In case you are curious about slice notation, this SO question Python Lists(Slice method) will give you more background.
Finally, it is not a good idea to use list as an identifier as Python already uses this identifier for its own data structure (which is the reason I added the "m" in front of the variable names)
That's because both list and list2 are referring to the same list after you did the assignment list2=list.
Try this to see if they are referring to the same objects or different:
id(list)
id(list2)
An example:
>>> list = [1, 2, 3, 4, 5]
>>> list2 = list
>>> id(list)
140496700844944
>>> id(list2)
140496700844944
>>> list.remove(3)
>>> list
[1, 2, 4, 5]
>>> list2
[1, 2, 4, 5]
If you really want to create a duplicate copy of list such that list2 doesn't refer to the original list but a copy of the list, use the slice operator:
list2 = list[:]
An example:
>>> list
[1, 2, 4, 5]
>>> list2
[1, 2, 4, 5]
>>> list = [1, 2, 3, 4, 5]
>>> list2 = list[:]
>>> id(list)
140496701034792
>>> id(list2)
140496701034864
>>> list.remove(3)
>>> list
[1, 2, 4, 5]
>>> list2
[1, 2, 3, 4, 5]
Also, don't use list as a variable name, because originally, list refers to the type list, but by defining your own list variable, you are hiding the original list that refers to the type list. Example:
>>> list
<type 'list'>
>>> type(list)
<type 'type'>
>>> list = [1, 2, 3, 4, 5]
>>> list
[1, 2, 3, 4, 5]
>>> type(list)
<type 'list'>
What will be the logic or code of this problem? The reverse() function does not take any argument and list[::-1] is also the same. How to do it in easy way?
Example, given:
list = [1,5,4,3,2,6]
Reversing 5...2, the output will be:
list = [1,2,3,4,5,6]
You could use list slice assignment, which modifies the list in-place:
>>> L = [1, 5, 4, 3, 2, 6]
>>> L[1:5] = L[4:0:-1]
>>> L
[1, 2, 3, 4, 5, 6]
You can reassign the slice of the list to that same slice in reverse
l = [1,5,4,3,2,6]
l[1:5] = l[1:5][::-1]
print(l)
#[1, 2, 3, 4, 5, 6]
You could do something like this:
l = [1,5,4,3,2,6]
index5 = l.index(5)
index2 = l.index(2)
l[index5:index2+1] = l[index2:index5-1:-1]
If you want it to be more explicit, you could use reversed:
l[index5:index2+1] = reversed(l[index5:index2+1])
Edit: Sorry, I misunderstood your question.
>>> l = [1, 5, 4, 3, 2, 6]
>>> temp = l[1:5]
>>> temp.reverse()
>>> l[1:5] = temp
>>> l
>>> [1, 2, 3, 4, 5, 6]
im trying to append and remove multiple objects instances from a list in Python. However, I couldn't find a short way to do it and had to use to for cycles ... is there any compact way to do it ?
Append to list:
# Create objects
specialAgent.append(Boid(1))
specialAgent.append(Boid(2))
for i in range(2):
boids.append(specialAgent[-1-i])
Remove from list:
# Destroy objects
for i in range(len(specialAgent)):
boids.remove(specialAgent[i])
You could use slice assignment:
>>> L = [1, 2, 3]
>>> L[3:] = [4, 5, 6]
>>> L
[1, 2, 3, 4, 5, 6]
>>> L[-3:] = []
>>> L
[1, 2, 3]
You can also append multiple items to a list using the .extend() list method:
>>> L.extend([4, 5, 6])
>>> L
[1, 2, 3, 4, 5, 6]
I'm sure this question has come up before, but I couldn't find an exact example.
I have 2 lists and want to append the second to the first, only of the values are not already there.
So far I have working code, but was wondering if there were a better, more "Pythonic" was of doing this:
>>> list1
[1, 2, 3]
>>> list2
[2, 4]
>>> list1.extend([x for x in list2 if x not in list1])
>>> list1
[1, 2, 3, 4]
EDIT
Based on comments made, this code does not satisfy adding only once, ie:
>>> list1 = [1,2,3]
>>> list2 = [2,4,4,4]
>>> list1.extend([x for x in list2 if x not in list1])
>>> list1
[1, 2, 3, 4, 4, 4]
How would I end up with only:
[1, 2, 3, 4]
If you want to maintain the order, you can use collections.OrderedDict like this
from collections import OrderedDict
from itertools import chain
list1, list2 = [1, 2, 3], [2, 4]
print list(OrderedDict.fromkeys(chain(list1, list2)))
# [1, 2, 3, 4]
If the order of the elements is not important, you can use the set like this
from itertools import chain
list1, list2 = [1, 2, 3], [2, 4]
print list(set(chain(list1, list2)))
# [1, 2, 3, 4]
A way could be using built in type set:
list(set(list1).union(list2))
You would need to store the result of the operation, if you wanted to extend list1 then you can assign it to list1:
list1=list(set(list1).union(list2))
Note: Keep in mind that this approach may not keep the order of the elements in the list.
Hope this helps!