For example, we have these lists:
l1 = [1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4]
l2 = [11, 11, 2]
l3 = [5, 6]
l4 = [1, 2, 3, 3, 3]
Here, l2 and l3 have 2 numbers (11 and 2 for l2, and 5 and 6 for l3)
l1 has 4 numbers (1, 2, 3, and 4)
l4 has 3 numbers (1, 2, 3)
How can I calculate that? (assuming the list is unknown)
Thank you!
Convert the lists to sets and use len() to see how many unique numbers are in each of them. Something like this:
>>> l1 = [1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4]
>>> l2 = [11, 11, 2]
>>> l3 = [5, 6]
>>> l4 = [1, 2, 3, 3, 3]
>>> len(set(l1))
4
>>> len(set(l2))
2
>>> len(set(l3))
2
>>> len(set(l4))
3
>>>
And to see the unique elements, the following will show you them:
>>> set(l1)
{1, 2, 3, 4}
>>>
print(len(list(dict.fromkeys(l2)))
explanation:
len - method that return length of list
list - converts dict to list
dict.fromkeys - create dictionary from given list
(values that repeat will be appended to dictionary just once because its dictionary :) it couldnt have two definitions of one variable )
You can achieve this by using list of list:
def numbersList(l1):
return len(set(l1))
nList = [[1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4],[11, 11, 2], [5, 6], [1, 2, 3, 3, 3]]
for l in nList:
print(numbersList(l))
# if you want to add more list to list
print("After Append")
nList.append([3,3,3,5,5,5,6,6,6,7,7,7,8,8,9,10])
for l in nList:
print(numbersList(l))
Related
I have a list of integers. Each number can appear several times, the list is unordered.
I want to get the list of relative sizes. Meaning, if for example the original list is [2, 5, 7, 7, 3, 10] then the desired output is [0, 2, 3, 3, 1, 4]
Because 2 is the zero'th smallest number in the original list, 3 is one'th, etc.
Any clear easy way to do this?
Try a list comprehension with dictionary and also use set for getting unique values, like below:
>>> lst = [2, 5, 7, 7, 3, 10]
>>> newl = dict(zip(range(len(set(lst))), sorted(set(lst))))
>>> [newl[i] for i in lst]
[0, 2, 3, 3, 1, 4]
>>>
Or use index:
>>> lst = [2, 5, 7, 7, 3, 10]
>>> newl = sorted(set(lst))
>>> [newl.index(i) for i in lst]
[0, 2, 3, 3, 1, 4]
>>>
I had tried to make a list free of duplicates from another defined list using list comprehension as follows,
num = [1, 2, 2, 2, 3, 3, 4, 4, 4, 5]
my_list = []
my_list = [x for x in num if x not in my_list]
Upon calling my_list, I get back the same array
[1, 2, 2, 2, 3, 3, 4, 4, 4, 5]
Could anyone kindly explain why this is happening?
Using set is more feasible than an if condition along with for loop:
num = [1, 2, 2, 2, 3, 3, 4, 4, 4, 5]
my_list = list(set(num))
print(my_list)
Ouput:
[1, 2, 3, 4, 5]
my_list isn't updated until after the comprehension is complete. During the comprehension my_list is an empty list.
If order matters the approach you want to take is:
num = [1, 2, 2, 2, 3, 3, 4, 4, 4, 5]
my_list = []
check_set = set()
for x in num:
if x not in check_set:
my_list.append(x)
check_set.add(x)
If order does not matter:
my_list = list(set(num))
you should try something like this :
In [99]: num = [1, 2, 2, 2, 3, 3, 4, 4, 4, 5]
...: my_list = []
In [100]: [my_list.append(item) for item in num if item not in my_list]
Out[100]: [None, None, None, None, None]
In [101]: my_list
Out[101]: [1, 2, 3, 4, 5]
The list is updated after the list comprehension process is complete because which the duplicates are still present.
You can try this list comprehension.
my_list=[]
num = [1, 2, 2, 2, 3, 3, 4, 4, 4, 5]
my_list=[my_list.append(x) or x for x in num if x not in my_list]
# [1,2,3,4,5]
If you don't care about the order.
my_lst=list(set(num))
From Python3.6 and above dictionaries store the insertion order or use collections.OrderedDict. So, you can try this.
num = [1, 2, 2, 2, 3, 3, 4, 4, 4, 5]
my_list=list(dict.fromkeys(num).keys())
You can use seen set to keep track of the elements that are seen. If an element in in seen don't add it to my_list.
num = [1, 2, 2, 2, 3, 3, 4, 4, 4, 5]
seen=set()
my_list=[]
for x in num:
if x not in seen:
seen.add(x)
my_list.append(x)
my_list
# [1,2,3,4,5]
I'm working on a project and I need to repeat a list within a list a certain number of times. Obviously, L.append(L) just adds the elements again without creating separate lists. I'm just stumped on how to make the lists separate within the big list.
In short form, this is what I have:
L = [1,2,3,4,5]
If I wanted to to repeat it, say, 3 times so I'd have:
L = [[1,2,3,4,5],[1,2,3,4,5],[1,2,3,4,5]]
How do I achieve this? I'm looking for lists within the big list.
No need for any functions:
>>> L = [1,2,3,4,5]
>>> [L]*3
[[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
However, you should note that if you change one value in any of the lists, all the others will change because they reference the same object.
>>> mylist = [L]*3
>>> mylist[0][0] = 6
>>> print mylist
[[6, 2, 3, 4, 5], [6, 2, 3, 4, 5], [6, 2, 3, 4, 5]]
>>> print L
[6, 2, 3, 4, 5]
To avoid this:
>>> L = [1,2,3,4,5]
>>> mylist = [L[:] for _ in range(3)]
>>> mylist[0][0] = 6
>>> print L
[1, 2, 3, 4, 5]
>>> print mylist
[[6, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
Notice how L didn't change, and only the first list in mylist changed.
Thanks everyone in the comments for helping :).
I am trying to sort two lists together:
list1 = [1, 2, 5, 4, 4, 3, 6]
list2 = [3, 2, 1, 2, 1, 7, 8]
list1, list2 = (list(x) for x in zip(*sorted(zip(list1, list2))))
Anyway, doing this gives me on output
list1 = [1, 2, 3, 4, 4, 5, 6]
list2 = [3, 2, 7, 1, 2, 1, 8]
while I would want to keep the initial order for equal number 4 in the first list: what I want is
list1 = [1, 2, 3, 4, 4, 5, 6]
list2 = [3, 2, 7, 2, 1, 1, 8]
What do I have to do? I wouldn't want to use loop for bubble-sorting. Any help appreciated.
Use a key parameter for your sort that only compares the first element of the pair. Since Python's sort is stable, this guarantees that the order of the second elements will remain the same when the first elements are equal.
>>> from operator import itemgetter
>>> [list(x) for x in zip(*sorted(zip(list1, list2), key=itemgetter(0)))]
[[1, 2, 3, 4, 4, 5, 6], [3, 2, 7, 2, 1, 1, 8]]
Which is equivalent to:
>>> [list(x) for x in zip(*sorted(zip(list1, list2), key=lambda pair: pair[0]))]
[[1, 2, 3, 4, 4, 5, 6], [3, 2, 7, 2, 1, 1, 8]]
The trick here is that when Python does tuple comparisons, it compares the elements in order from left to right (for example, (4, 1) < (4, 2), which is the reason that you don't get the ordering you want in your particular case). That means you need to pass in a key argument to the sorted function that tells it to only use the first element of the pair tuple as its sort expression, rather than the entire tuple.
This is guaranteed to retain the ordering you want because:
sorts are guaranteed to be stable. That means that when multiple records have the same key, their original order is preserved.
(source)
>>> list1 = [1, 2, 5, 4, 4, 3, 6]
>>> list2 = [3, 2, 1, 2, 1, 7, 8]
>>>
>>> list1, list2 = (list(x) for x in zip(*sorted(zip(list1, list2), key=lambda pair: pair[0])))
>>>
>>> print list1
[1, 2, 3, 4, 4, 5, 6]
>>> print list2
[3, 2, 7, 2, 1, 1, 8]
In you code the sorting is performed basing on the first and the second elements of the tuples, so the resulting second list elements are in the sorted order for the same elements of the first list.
To avoid sorting based on the second list, just specify that only the elements from the first list should be used in the comparison of the tuples:
>>> from operator import itemgetter
>>> list1, list2 = (list(x) for x in zip(*sorted(zip(list1, list2),key=itemgetter(0))))
>>> list1, list2
([1, 2, 3, 4, 4, 5, 6], [3, 2, 7, 2, 1, 1, 8])
itemgetter(0) takes the first element from each tuple, which belongs to the first list.
Can't figure out how to do this in a pretty way :
I have a list of n elements,
I want to access every m elements of the list.
For example : [1, 2, 3, 4, 5] and m = 2 would give
[2, 4]
I can do it simply with a loop, but ins't there a more "pythonic" way?
Thanks by advance !
EDIT :
Seems like I forgot something.
I want, not only get those values but modify them.
I tried slicing a[::2] = 3, but it doesn't work. . .
I'm searching for something similar
Slicing syntax does this for you:
>>> my_list = range(10)
>>> my_list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> my_list[::2]
[0, 2, 4, 6, 8]
>>> my_list[1::2]
[1, 3, 5, 7, 9]
Here's a way to wrap a list to get the original assignment behavior you wanted, but I'm not sure I'd recommend it:
class AssignableSlice(list):
def __setitem__(self, i, v):
if isinstance(i, slice):
for ii in xrange(*i.indices(len(self))):
self[ii] = v
else:
super(AssignableSlice, self).__setitem__(i, v)
a = AssignableSlice(range(10))
print a
a[::2] = 3
print a
a[1::3] = 99
print a
produces:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[3, 1, 3, 3, 3, 5, 3, 7, 3, 9]
[3, 99, 3, 3, 99, 5, 3, 99, 3, 9]
Ned's answer shows how to use slices to access a portion of the list. You can also assign to a slice, but you need to assign a list to the slice, for example:
>>> my_list = range(5)
>>> my_list
[0, 1, 2, 3, 4]
>>> my_list[::2]
[0, 2, 4]
>>> my_list[::2] = [0, 0, 0]
>>> my_list
[0, 1, 0, 3, 0]
Note that when the step in your slice is anything besides the default of 1 the list that you assign needs to be the same length, however with a default step you can actually change the size of the list with slice assignment:
>>> my_list = range(5)
>>> my_list
[0, 1, 2, 3, 4]
>>> my_list[:1]
[0]
>>> my_list[:1] = [4, 3, 2] # replace the first item with 3 new items
>>> my_list
[4, 3, 2, 1, 2, 3, 4]
>>> my_list[2:5]
[2, 1, 2]
>>> my_list[2:5] = [] # remove the middle three items from the list
>>> my_list
[4, 3, 3, 4]
I juste found a way to do what I want using slicing.
The following :
candidates[::2] = [1] * len(candidates[::2])
will replace every 2 elements of candidates by 1