How to get duplicates in sorted list with O(n) python - python-3.x

Hear i have a list, and i have to get duplicates from it. So i can use solution like this:
arr = [1, 1, 2, 3, 4, 4, 5]
def get_duplicates(arr):
duplicates = []
for index in range(len(arr)-1):
if arr[index] == arr[index+1]:
duplicates.append(arr[index])
return duplicates
print(*duplicates)
Ok, what if i have three or more duplicates in my list? I did something like that:
arr = [1, 1, 1, 2, 3, 4, 4, 4, 4, 5]
def get_duplicates(arr):
duplicates = []
for index in range(len(arr)-1):
if arr[index] == arr[index+1]:
duplicates.append(arr[index])
return duplicates
print(*set(duplicates))
Is that both my code works with O(n) or not? I just dont know what is speed of set() function in python, but i think that first for loop takes O(n),
if set() takes O(n), it doesnt matter, because finally i will have O(2n) = O(n) in this case.
Do i solve that task correctly, or my code is not effective? Smart people, help me please))
If u know how to do it in wright direction, explain me please.

Here is a version that is clearly O(n):
def get_duplicates(arr):
last_duplicate = None
duplicates = []
for i,v in enumerate(arr[1:]):
if v==arr[i-1] and v!=last_duplicate:
duplicates.append(v)
last_duplicate = v
return duplicates
Note that this assumes, as your original code does, that duplicates will be adjacent to one another. It also assumes that the first duplicate is not None.

Related

The del function in the for loop removes every second element. I want to delete all of them until the condition is met

a = [0,0,0,0,0,0,0,0,0,1,2,3,4,0,0]
for i in a:
if i < 3:
del a[0]
print(a)
[0, 0, 0, 1, 2, 3, 4]
should be:
[3,4,0,0]
You are using i in a confusing way, since you're not using it as an index (which is kinda the norm) but as an iterator. Just for readability I would suggest changing the iterator name to something more descriptive.
If I understand you're question correctly, you want to delete the first element, until it is bigger or equal 3. If that is your question, you could do it like this:
a = [0,0,0,0,0,0,0,0,0,1,2,3,4,0,0]
while a[0]<3:
del a[0]
print(a) # [3,4,0,0]
a = [0,0,0,0,0,0,0,0,0,1,2,3,4]
n= []
for i in range(len(a)):
if(a[i]<3):
continue
else:
n.append(a[i])
print(n) # [3,4]

How to delete certain element(s) from an array?

I have a 2d array, how can I delete certain element(s) from it?
x = [[2,3,4,5,2],[5,3,6,7,9,2],[34,5,7],[2,46,7,4,36]]
for i in range(len(x)):
for j in range(len(x[i])):
if x[i][j] == 2:
del x[i][j]
This will destroy the array and returns error "list index out of range".
you can use pop on the list item. For example -
>>> array = [[1,2,3,4], [6,7,8,9]]
>>> array [1].pop(3)
>>> array
[[1, 2, 3, 4], [6, 7, 8]]
I think this can solve your problem.
x = [[2,3,4,5,2],[5,3,6,7,9,2],[34,5,7],[2,46,7,4,36]]
for i in range(len(x)):
for j in range(len(x[i])):
if j<len(x[i]):
if x[i][j] == 2:
del x[i][j]
I have tested it locally and working as expected.Hope it will help.
Mutating a list while iterating over it is always a bad idea. Just make a new list and add everything except those items you want to exclude. Such as:
x = [[2,3,4,5,2],[5,3,6,7,9,2],[34,5,7],[2,46,7,4,36]]
new_array = []
temp = []
delete_val = 2
for list_ in x:
for element in list_:
if element != delete_val:
temp.append(element)
new_array.append(temp)
temp = []
x = new_array
print(x)
Edit: made it a little more pythonic by omitting list indices.
I think this is more readable at the cost of temporarily more memory usage (making a new list) compared to the solution that Sai prateek has offered.

Fastest way to find all the indexes of maximum value in a list - Python

I am having list which as follows
input_list= [2, 3, 5, 2, 5, 1, 5]
I want to get all the indexes of maximum value. Need efficient solution. The output will be as follows.
output = [2,4,6] (The above list 5 is maximum value in a list)
I have tried by using below code
m = max(input_list)
output = [i for i, j in enumerate(a) if j == m]
I need to find any other optimum solution.
from collections import defaultdict
dic=defaultdict(list)
input_list=[]
for i in range(len(input_list)):
dic[input_list[i]]+=[i]
max_value = max(input_list)
Sol = dic[max_value]
You can use numpy (numpy arrays are very fast):
import numpy as np
input_list= np.array([2, 3, 5, 2, 5, 1, 5])
i, = np.where(input_list == np.max(input_list))
print(i)
Output:
[2 4 6]
Here's the approach which is described in comments. Even if you use some library, fundamentally you need to traverse at least once to solve this problem (considering input list is unsorted). So even lower bound for the algorithm would be Omega(size_of_list). If list is sorted we can leverage binary_search to solve the problem.
def max_indexes(l):
try:
assert l != []
max_element = l[0]
indexes = [0]
for index, element in enumerate(l[1:]):
if element > max_element:
max_element = element
indexes = [index + 1]
elif element == max_element:
indexes.append(index + 1)
return indexes
except AssertionError:
print ('input_list in empty')
Use a for loop for O(n) and iterating just once over the list resolution:
from itertools import islice
input_list= [2, 3, 5, 2, 5, 1, 5]
def max_indexes(l):
max_item = input_list[0]
indexes = [0]
for i, item in enumerate(islice(l, 1, None), 1):
if item < max_item:
continue
elif item > max_item:
max_item = item
indexes = [i]
elif item == max_item:
indexes.append(i)
return indexes
Here you have the live example
Think of it in this way, unless you iterate through the whole list once, which is O(n), n being the length of the list, you won't be able to compare the maximum with all values in the list, so the best you can do is O(n), which you already seems to be doing in your example.
So I am not sure you can do it faster than O(n) with the list approach.

Python: How to find the average on each array in the list?

Lets say I have a list with three arrays as following:
[(1,2,0),(2,9,6),(2,3,6)]
Is it possible I get the average by diving each "slot" of the arrays in the list.
For example:
(1+2+2)/3, (2+0+9)/3, (0+6+6)/3
and make it become new arraylist with only 3 integers.
You can use zip to associate all of the elements in each of the interior tuples by index
tups = [(1,2,0),(2,9,6),(2,3,6)]
print([sum(x)/len(x) for x in zip(*tups)])
# [1.6666666666666667, 4.666666666666667, 4.0]
You can also do something like sum(x)//len(x) or round(sum(x)/len(x)) inside the list comprehension to get an integer.
Here are couple of ways you can do it.
data = [(1,2,0),(2,9,6),(2,3,6)]
avg_array = []
for tu in data:
avg_array.append(sum(tu)/len(tu))
print(avg_array)
using list comprehension
data = [(1,2,0),(2,9,6),(2,3,6)]
comp = [ sum(i)/len(i) for i in data]
print(comp)
Can be achieved by doing something like this.
Create an empty array. Loop through your current array and use the sum and len functions to calculate averages. Then append the average to your new array.
array = [(1,2,0),(2,9,6),(2,3,6)]
arraynew = []
for i in range(0,len(array)):
arraynew.append(sum(array[i]) / len(array[i]))
print arraynew
As you were told in the comments with sum and len it's pretty easy.
But in python I would do something like this, assuming you want to maintain decimal precision:
list = [(1, 2, 0), (2, 9, 6), (2, 3, 6)]
res = map(lambda l: round(float(sum(l)) / len(l), 2), list)
Output:
[1.0, 5.67, 3.67]
But as you said you wanted 3 ints in your question, would be like this:
res = map(lambda l: sum(l) / len(l), list)
Output:
[1, 5, 3]
Edit:
To sum the same index of each tuple, the most elegant method is the solution provided by #PatrickHaugh.
On the other hand, if you are not fond of list comprehensions and some built in functions as zip is, here's a little longer and less elegant version using a for loop:
arr = []
for i in range(0, len(list)):
arr.append(sum(l[i] for l in list) / len(list))
print(arr)
Output:
[1, 4, 4]

How to assing values to a dictionary

I am creating a function which is supposed to return a dictionary with keys and values from different lists. But I amhavin problems in getting the mean of a list o numbers as values of the dictionary. However, I think I am getting the keys properly.
This is what I get so far:
def exp (magnitudes,measures):
"""return for each magnitude the associated mean of numbers from a list"""
dict_expe = {}
for mag in magnitudes:
dict_expe[mag] = 0
for mea in measures:
summ = 0
for n in mea:
summ += n
dict_expe[mag] = summ/len(mea)
return dict_expe
print(exp(['mag1', 'mag2', 'mag3'], [[1,2,3],[3,4],[5]]))
The output should be:
{mag1 : 2, mag2: 3.5, mag3: 5}
But what I am getting is always 5 as values of all keys. I thought about the zip() method but im trying to avoid it as because the it requieres the same length in both lists.
An average of a sequence is sum(sequence) / len(sequence), so you need to iterate through both magnitudes and measures, calculate these means (arithmetical averages) and store it in a dictionary.
There are much more pythonic ways you can achieve this. All of these examples produce {'mag1': 2.0, 'mag2': 3.5, 'mag3': 5.0} as result.
Using for i in range() loop:
def exp(magnitudes, measures):
means = {}
for i in range(len(magnitudes)):
means[magnitudes[i]] = sum(measures[i]) / len(measures[i])
return means
print(exp(['mag1', 'mag2', 'mag3'], [[1, 2, 3], [3, 4], [5]]))
But if you need both indices and values of a list you can use for i, val in enumerate(sequence) approach which is much more suitable in this case:
def exp(magnitudes, measures):
means = {}
for i, mag in enumerate(magnitudes):
means[mag] = sum(measures[i]) / len(measures[i])
return means
print(exp(['mag1', 'mag2', 'mag3'], [[1, 2, 3], [3, 4], [5]]))
Another problem hides here: i index belongs to magnitudes but we are also getting values from measures using it, this is not a big deal in your case if you have magnitudes and measures the same length but if magnitudes will be larger you will get an IndexError. So it seems to me like using zip function is what would be the best choice here (actually as of python3.6 it doesn't require two lists to be the same length, it will just use the length of shortest one as the length of result):
def exp(magnitudes, measures):
means = {}
for mag, mes in zip(magnitudes, measures):
means[mag] = sum(mes) / len(mes)
return means
print(exp(['mag1', 'mag2', 'mag3'], [[1, 2, 3], [3, 4], [5]]))
So feel free to use the example which suits your requirements of which one you like and don't forget to add docstring.
More likely you don't need such pythonic way but it can be even shorter when dictionary comprehension comes into play:
def exp(magnitudes, measures):
return {mag: sum(mes) / len(mes) for mag, mes in zip(magnitudes, measures)}
print(exp(['mag1', 'mag2', 'mag3'], [[1, 2, 3], [3, 4], [5]]))

Resources