For loop resulting in wrong output - python

The code snippet below results in [5,7,18,23,50], why 5 is not getting removed from the resultant list?
list1 = [11, 5, 17, 18, 23, 50]
not_needed = {11, 5}
for e in list1:
if e in not_needed:
list1.remove(e)
else:
pass
print(list1)

Because you are modifying the list as it is being iterated over.
When you read the first item, it is 11 so it gets removed.
When you read the second item, it is 17, because the first item
was removed. The item 5 is now the new first item and you never get
to check it.

Because once the 11 is removed, the 5 gets skipped during iteration. This is why you never iterate over a list and remove from it at the same time.
list1 = [11, 5, 17, 18, 23, 50]
not_needed = {11, 5}
for e in not_needed:
list1.remove(e)
print(list1)
Gives:
[17, 18, 23, 50]

Use list comprehension when looping over a list and modifying it at the same time.
list1 = [x for x in list1 if not x in not_needed]
list1
[17, 18, 23, 50]
Further details on this here:
https://www.analyticsvidhya.com/blog/2016/01/python-tutorial-list-comprehension-examples/

This is because after first iteration item 11 is deleted and it goes for second index which becomes 17 in list [5,17,18,23,50]
The best way to rectify this is to take result list so that you dont have to mutate "list1"
list1 = [11, 5, 17, 18, 23, 50]
not_needed = {11, 5}
result = []
for e in list1:
if e in not_needed:
pass
else:
result.append(e)
print(result)

for loop in python runs on the indexes not on each element.
When it finds 11 and removes it from list1, list1 becomes [5, 17, 18, 23, 50] but the loop is now on second element. So it misses 5 in the list.

Related

Python: Find count of elements of one list when condition in another list is fulfilled

Let's say I have two lists list1 and list2 as:
list1 = [ 3, 26, 17, 7, 35, 8, 14, 24 ]
list2 = [ long, long, long, short, short, short, short, short ]
I want to find the count of 'short' of list2 when elements in list1 > 10.
Expected output is 3, as 35, 14, 24 in list1 are > 10. and they corresponds to "short' in list 2.
If you want to treat these two lists as a list of pairs, you can zip them together, with something like the following.
Note that I'm using the sum function here to count the number of times the expression evaluates to True (with True automatically treated as 1 and False as 0).
# Assuming that `long` and `short` are arbitrary objects
long = object()
short = object()
list1 = [3, 26, 17, 7, 35, 8, 14, 24]
list2 = [long, long, long, short, short, short, short, short]
print(sum(num > 10 and category is short
for num, category in zip(list1, list2)))
Length of both the lists should be same then only you can apply corresponding element condition.
c=0 #counter variable
list1 = [ 3, 26, 17, 7, 35, 8, 14, 24 ]
list2 = ['long','long','long','short','short','short','short','short']
for x,y in enumerate(list2): #you can track the position and value with enumerate
if y=='short' and list1[x]>10:
c+=1
print(c)
#3
You can also do in one line with sum and generator expression
sum(1 for x,y in enumerate(list2) if y=='short' and list1[x]>10)
#3
You can use zip to iterate over both lists at the same time and increment a counter if a condition is met:
count=0
for x, y in zip(list1, list2):
if x>10 and y=="short":
count+=1
Keep in mind it will iterate until it reaches the end of the shorter iterable.
When used in an arithmetic context, True and False have effective values of 1 and 0 respectively. Therefore:
list1 = [ 3, 26, 17, 7, 35, 8, 14, 24 ]
list2 = ['long','long','long','short','short','short','short','short']
print(sum(x > 10 and y == 'short' for x, y in zip(list1, list2)))
Output:
3

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 (e.g. 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]

How do you find most duplicates in a 2d list?

I have a 2d list that i would like to return the most duplicates by using a list comprehension. For example, i have a list below
a = [[10, 15, 17,],[20,21,27],[10,15,17],[21,27,28],[21,27,28],[5,10,15],[15,17,20]]
I would like my result to be
b = [[10,15,17],[21,27,28]
The common solution for counting repetitions is collections.Counter:
from collections import Counter
a = [[10, 15, 17], [20, 21, 27], [10, 15, 17], [21, 27, 28], [21, 27, 28], [5, 10, 15], [15, 17, 20]]
# count duplicates
counts = Counter(map(tuple, a))
# find the maximum count (the values of counts are the duplicate count)
maximum_count = max(counts.values())
# filter and convert back to list
result = [list(e) for e, count in counts.items() if count == maximum_count]
print(result)
Output
[[10, 15, 17], [21, 27, 28]]
In your case in particular as the elements of the list are list, you need to convert them to tuples (to make them hashable), then just filter the list and keep the elements with maximum count.
One line splitted here:
[ a[k]
for k in range(len(a))
if a.count( a[k] ) > 1
and k == a.index( a[k] ) ]
The simplest way to do this to find the count for each element, and store the maximum count. Then, display all elements that have the maximum count (removing duplicates).
The below code will work for you:
a = [[10, 15, 17,],[20,21,27],[10,15,17],[21,27,28],[21,27,28],[5,10,15],[15,17,20]]
check=0
for i in a:
if a.count(i) > check:
check=a.count(i) #Check to see maximum count
b=[]
for i in a:
if a.count(i) == check: #Choosing elements with maximum count
if i not in b: #Eliminating duplicates
b.append(i)
print(b)
Output:
[[10, 15, 17], [21, 27, 28]]

How to inset items into list at sepcified intervals to match len of another list?

I have wrote a code which insert/duplicate items into list of smaller len to match len of bigger list.
code is:
l1=[big list of length:491]
l2=[small list of lenth: 153]
l= abs(len(l2)-len(l1))==> 338
i=0
j=1
while i<l:
l2.insert(j,l2[j])
j+=2
i += 1
But after some loops i get this error
IndexError: list index out of range
which is because l>len(l2) and the code/algo catches up to len(l2).
Is there a better solution to solve this?
what i am expecting is
l1 is any list of size 30 for example and l2=[1,2,3,4,5] output should be like [1,1,2,2,3,3,4,4,5,5]
I hope this solves your requirements:
l1=[1, 2, 3, 4, 5, 6, 7, 8]
l2=[11, 12, 13, 14, 15]
# Quotient of the lengths of both lists
quotient = float(len(l1)) / float(len(l2))
new_l = []
for i in range(len(l1)):
# Divide the quotient from the index to get value of l2 which will be added.
new_l.append(l2[int(i/quotient)])
print(new_l)
Ouput:
>> [11, 11, 12, 12, 13, 14, 14, 15]

count number of sublist that contain 3 common elements in Python 3

I am using Python 3.4 and Wing Personal in Windows 7.
I have a list of a list of ints and a second list that contains 3 ints. I would like to identify how many times all 3 elements of list [b] appear in list [a].
a=[[1, 6, 11,12, 14, 15], [4, 11, 23, 32, 45, 48],
[3, 7, 11, 14, 15, 17], [1, 8, 14, 24, 45, 53],
[2, 5, 9, 24, 34, 40], [10, 11,13, 14, 15, 22, 36]]
b=[11,14,15]
count =0
anotherList = []
for sublist in a:
for element in b:
if element in sublist:
anotherList.append(element)
count+=1
print (anotherList)
print (count/3)
Here the count should be 3, not 3.6 and while floor division would cure this it does not help if list [a] contains 20 sublist and a single 14 occurred in 6 of the sublist.
The problem is this counts the total number of times any of the elements in list [b] occur in list [a], rather than the pattern of all 3 elements. I divided by 3 thinking that would make count correct till I realized if only a 14 occurred in a list that was also counted so the count would be off.
Note that index is different in each list and sometimes another element occurs in between the elements I want to identify. ie, the elements are not always together as 11,14,15. sometimes there is another element in between.
I considered trying to delete all numbers except 11,14,15 then delete all list less than 3 elements long but somehow that does not seem to be the way to do it.
Any help is appreciated.
Why not simply use set? Convert b to set a see if it is a subset of the items in the list using the set.issubset method:
b = {11,14,15} #notice the {} braces or use `set([11,14,15])`
print sum(b.issubset(x) for x in a)
You can use all with sum:
print(sum(all(ele in sub for ele in b ) for sub in a))

Categories

Resources