Removing duplicates in a list (Python 3.8.3) - python-3.x

I want to just understand why the below code is not very good at removing duplicates:
numbers = [4, 4, 4, 10, 10, 10, 20, 20, 2]
for duplicates in numbers:
numbers.count(duplicates)
if numbers.count(duplicates) > 1:
numbers.remove(duplicates)
numbers.sort()
print(numbers)
The final output is: [2, 4, 10, 10, 20]
This could just be a fundamental error in my understanding of the methods used, but I would like to know what is wrong here.
PS. I'm aware I could do an easier version of this code posted below, but I am just curious.
Easier version of above code:
numbers = [4, 4, 4, 10, 10, 10, 20, 20, 2]
unique_list = []
for duplicates_check in numbers:
if duplicates_check not in unique_list:
unique_list.append(duplicates_check)
unique_list.sort()
print(unique_list)
Thanks in advance for your help!

Modifying the list as you're iterating over it is a bad idea (since the loop gets "confused" about which index it's on).
Since you're sorting the numbers in the end, you apparently don't care about the order.
Just do
numbers = sorted(set(numbers))
– that is, convert the numbers to a set; sets can only contain each element once, then use sorted() to sort the set into a new list.
If you would care about the order,
def unique_in_order(iterable):
seen = set()
for item in iterable:
if item not in seen:
seen.add(item)
yield item
numbers = list(unique_in_order(iterable))
is your recipe.

Related

why inserting some element into a list giving None instead of the whole lists? [duplicate]

#!/usr/bin/python
numbers = [1, 2, 3, 5, 6, 7]
clean = numbers.insert(3, 'four')
print clean
# desire results [1, 2, 3, 'four', 5, 6, 7]
I am getting "None". What am I doing wrong?
Mutating-methods on lists tend to return None, not the modified list as you expect -- such metods perform their effect by altering the list in-place, not by building and returning a new one. So, print numbers instead of print clean will show you the altered list.
If you need to keep numbers intact, first you make a copy, then you alter the copy:
clean = list(numbers)
clean.insert(3, 'four')
this has the overall effect you appear to desire: numbers is unchanged, clean is the changed list.
The insert method modifies the list in place and does not return a new reference. Try:
>>> numbers = [1, 2, 3, 5, 6, 7]
>>> numbers.insert(3, 'four')
>>> print numbers
[1, 2, 3, 'four', 5, 6, 7]
The list.insert() operator doesn't return anything, what you probably want is:
print numbers
insert will insert the item into the given list. Print numbers instead and you'll see your results. insert does not return the new list.

Python - Invert list order

I want to invert list order without changing the values.
The original list is the following:
[15, 15, 10, 8, 73, 1]
While the resulting expecting list is:
[10, 8, 15, 15, 1, 73]
The example has been taken from a real data handling problem from a more complex pandas data frame.
I proposed a list problem only to simplify the issue. So, it can also be a pandas function.
zlist = int(len(list)/2)
for i in range(0, zlist):
a, b = list.index(sorted(list, reverse=True)[i]), list.index(sorted(list,reverse=False)[i])
list[b], list[a] = list[a], list[b]

Creating a for loop to find mean for a specific section of list

I would like to loop a list to find the mean for a specific window.
What I mean by this is for example:
num_list=[1,2,3,4,5]
window=3
Thus, I would find the mean for [1,2,3] , [2,3,4] and [3,4,5].
How I approached this was as the following:
average_list=[]
first_list=num_list[0:window]
def mean(data):
n=len(data)
mean=sum(data)/n
return mean
for i in first_list:
first_value=mean(i)
average_list.append(first_value)
I am not quite sure how to incorporate the other two lists without typing it individually. Any help would be greatly appreciated!!
You can use list comprehension to iterate num_list taking slices of length window.
Try this:
mean_lst = [sum(num_list[i:i+window])/window for i in range(len(num_list)-window + 1)]
Result is
[2.0, 3.0, 4.0]
Here's the most obvious solution to your problem:
for i in range(list_len-window+1):
average_list.append(mean(num_list[i:i+window]))
It does work properly, but it isn't optimal. Consider num_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and window = 5. Using obvious method, the code will first calculate the sum of [1, 2, 3, 4, 5], then divide by 5, then it will calculate the sum of [2, 3, 4, 5, 6], then divide by 5, and so on.
This code is clearly doing a lot more calculations than it needs to. An optimal way would be to calculate the mean of first window and then for calculating mean of every consecutive window remove the first_element_of_previous_window/window_size (1/5 for 2nd window) and add last_element_of_current_window/window_size (6/5 for 2nd window) to the mean of previous window. This approach avoids a lot of unnecessary calculations.
Code Implementation:
prev_mean = mean(num_list[:window])
average_list = [prev_mean]
for i in range(1, list_len-window+1):
prev_mean -= num_list[i-1] / window
prev_mean += num_list[i+window-1] / window
average_list.append(prev_mean)

Why is the output of this code only even numbers between 1 and 121?

A=list(range(1,121))
for i in A:
A.remove(i)
print(A)
Shouldn't it be empty? I really don't get this..
You typically don't want to modify lists you're iterating over because you will get weird results like what you're running into.
You have a list of numbers, 1-121. You remove the first one, everything shifts down in memory so 2 is now in the zeroeth position. Do range 2-122 and you'll get only odd numbers.
x = [1, 2, 3, 4, 5, 6]
for i in x:
x.remove(i)
#first time through x = [2, 3, 4, 5, 6]
# ^ i is still pointing here though and the next time
# through it will be pointing at 3 (i = 2)

How to use iter and next in a function to return a list of peaks?

Problem:
I need to define a peaks function which passed to an iterable as parameter, by computing this iterable, the function should return a list of peaks. The only data structure that I can create is the list is returning; use no intermediate data structures to help the computation: e.g., I cannot create a list with all the values in the iterable. Note that I also cannot assume the argument is indexable, nor can I compute len for it: it is just iterable.
For example:
peaks([0,1,-1,3,8,4,3,5,4,3,8]) returns [1, 8, 5].
This result means the values 1, 8, and 5 are strictly bigger than the values immediately preceding and following them.
def peaks(iterable):
l=[]
i=iter(iterable)
v=next(i)
try:
while True:
if v>next(iter(iterable)):
l.append(v)
v=next(i)
except StopIteration:
pass
return l
Calling these should give me:
peaks([0,1,-1,3,8,4,3,5,4,3,8]) --> [1,8,5]
peaks([5,2,4,9,6,1,3,8,0,7]) -->[9,8]
But I am getting:
peaks([0,1,-1,3,8,4,3,5,4,3,8]) --> [1, 3, 8, 4, 3, 5, 4, 3, 8]
peaks([5,2,4,9,6,1,3,8,0,7]) --> [9, 6, 8, 7]
Please help me with this problem, I have spent so much time on it and am making no progress on it. And, I don't know how to write the if statement to check the values immediately preceding and following. Any helps would be great! Actual codes would be really appreciated since my English is bad.
def peaks(L):
answer = []
a,b,c = itertools.tee(L, 3)
next(b)
next(c)
next(c)
for first, second, third in zip(a,b,c):
if first <= second >= third:
answer.append(second)
return answer
In [61]: peaks([0,1,-1,3,8,4,3,5,4,3,8])
Out[61]: [1, 8, 5]
In [62]: peaks([5,2,4,9,6,1,3,8,0,7])
Out[62]: [9, 8]

Resources