Last index of duplicate items in a python list - python

Does anyone know how I can get the last index position of duplicate items in a python list containing duplicate and non-duplicate items?
I have a list sorted in ascending order with [1, 1, 1, 2, 2, 3, 3, 4, 5]
I want it to print the last index of duplicate items and index on non-duplicate items like this
2
4
6
7
8
I tried doing this way but could only print the starting index of duplicate elements and misssed non-duplicate items.
id_list = [1, 1, 1, 2, 2, 3, 3, 4, 5]
for i in range(len(id_list)):
for j in range(i+1,len(id_list)):
if id_list[i]==id_list[j]:
print(i)

Loop on the list using enumerate to get indexes & values, and use a dictionary and retain the last index (last index "wins" when there are duplicates). In the end, sort the indexes (as dictionaries aren't ordered, but you can use an OrderedDict):
import collections
lst = [1, 1, 1, 2, 2, 3, 3, 4, 5]
d = collections.OrderedDict()
for i,v in enumerate(lst):
d[v] = i
print(list(d.values()))
prints:
[2, 4, 6, 7, 8]
The advantage of this solution is that it works even if the duplicates aren't consecutive.
Python 3.7 guarantees the order of the base dictionaries so a simple dict comprehension solves it:
{v:i for i,v in enumerate(lst)}.values()

You can use enumerate and check the next index in the list. If an element is not equal to the element in the next index, it is the last duplicate:
lst = [1, 1, 1, 2, 2, 3, 3, 4, 5]
result = [i for i, x in enumerate(lst) if i == len(lst) - 1 or x != lst[i + 1]]
print(result)
# [2, 4, 6, 7, 8]

You can use a list comprehension with enumerate and zip. The last value will always be in scope, so we can include this at the end explicitly.
L = [1, 1, 1, 2, 2, 3, 3, 4, 5]
res = [idx for idx, (i, j) in enumerate(zip(L, L[1:])) if i != j] + [len(L) - 1]
print(res)
# [2, 4, 6, 7, 8]

Related

Remove specific identical subsequent values in Python list [duplicate]

This question already has answers here:
Python: Remove duplicates for a specific item from list
(9 answers)
Closed 2 years ago.
I have the list:
[1, 2, 3, 3, 4, 4, 5, 2, 3, 3]
and want to obtain:
[1, 2, 3, 3, 4, 5, 2, 3, 3]
That is I don't want any 4s in my list that are next to each other.
How do I do this without importing any packages?
In [289]: L = [1,2,3,3,4,4,5,2,3,3]
In [290]: answer = [L[0]]
In [291]: for n in L[1:]:
...: if n == answer[-1] == 4:
...: continue
...: answer.append(n)
...:
In [292]: answer
Out[292]: [1, 2, 3, 3, 4, 5, 2, 3, 3]
Use the built-in zip() function:
l = [1, 2, 3, 3, 4, 4, 5, 2, 3, 3]
l = [l[0]] + [j for i, j in zip(l, l[1:]) if not i == 4 == j]
print(l)
Output:
[1, 2, 3, 3, 4, 5, 2, 3, 3]
Explanation:
This line:
[j for i, j in zip(l, l[1:]) if not i == 4 == j]
is a list comprehension, where j is a variable that iterates through all the values of l, excluding the first value, and i is the value right before j in each iteration.
Only add j to the list if the value before it, i, os not equal to 4 while j is also equal to 4.
Since j omits the first value, concatenate the first value to the beginning of the list with [l[0]] + .

trying to merge two list ,placing their item alternative to each other in pyhton

guys i have to make one list ,by using two distinct list ,and items inside the final list is placed in such a order that ,first element of first list lie just after first element of second list,(lst1=[x1,x2,x3], lst2=[y1,y2,y3] , lst=[x1,y1,x2,y2,x3,y3])
input
lst1=[3,4,7]
lst2=[2,5,1]
ti=0
for yt in range(len(lst1)+1):
if yt %2==0:
lst1.insert(yt,lst2[ti])
ti+=1
print(lst1)
output
[2, 3, 5, 4, 7]
expected
[2, 3, 5, 4, 1, 7]
also wanna know my mistake .
any possible help will be appriciated
Use zip or chain.from_iterable
result = []
for x in zip(lst2, lst1):
result.extend(x)
or
from itertools import chain
list(chain.from_iterable(zip(lst2, lst1)))
[2, 3, 5, 4, 1, 7]
the loop range is wrong in your code:
lst1=[3,4,7]
lst2=[2,5,1]
ti=0
for yt in range(len(lst1)+len(lst2)-1): # <------ here
if yt %2==0:
lst1.insert(yt,lst2[ti])
ti+=1
print(lst1)
You can use zip and itertool's chain
from itertools import chain
li = list(chain(*zip(lst2,lst1)))
Or
li = [j for i in zip(lst2,lst1) for j in i]
li:
[2, 3, 5, 4, 1, 7]
Edit:
Explanation:
3,4,7
0,1,2
first insertion at 0th pos:
2,3,4,7
0,1,2,3
second insertion at 2nd pos:
2,3,5,4,7
0,1,2,3,4
third insertion at 4th pos:
2,3,5,4,1,7
0,1,2,3,4,5
range will be 0,1,2,3,4 [0,5)
expected = [x for tup in zip(lst2,lst1) for x in tup]
Output:
[2, 3, 5, 4, 1, 7]
Try this
lst1 = [3, 4, 7]
lst2 = [2, 5, 1]
lst3 = []
for i in zip(lst2, lst1):
lst3.extend(i)
print(lst3)
Output will this:
[2, 3, 5, 4, 1, 7]

Remove duplicate elements from list when there are many duplicate elements are present

I'm trying to remove a duplicate element from a list, it is not able to remove it ("1"), can somebody explain what I'm doing wrong
lst=[1,2,3,4,1,1,1,5,6,7,1,2]
for i in lst:
print(i)
if i==1:
lst.remove(i)
expected output -
[2,3,4,5,6,7,2]
actual output -
[2,3,4,5,6,7,1,2]
Using list comprehension:
Ex.
lst=[1,2,3,4,1,1,1,5,6,7,1,2]
new_list = [x for x in lst if x != 1]
print(new_list)
O/P:
[2, 3, 4, 5, 6, 7, 2]
OR
Remove all duplicate element from list, use set
Ex.
lst=[1,2,3,4,1,1,1,5,6,7,1,2]
print(list(set(lst)))
O/P:
[1, 2, 3, 4, 5, 6, 7]

Getting sublist with repeated elements in Python [duplicate]

I faced some problem with solving the next problem:
We have a list of elements (integers), and we should return a list consisting of only the non-unique elements in this list. Without changing order of the list
I think the best way is to delete or remove all unique element.
Take note that I just start to learn python and would like only the simplest solutions.
Here is my code:
def checkio(data):
for i in data:
if data.count(i) == 1: #if element seen in the list just ones, we delet this el
ind = data.index(i)
del data[ind]
return data
Your function can be made to work by iterating over the list in reverse:
def checkio(data):
for index in range(len(data) - 1, -1, -1):
if data.count(data[index]) == 1:
del data[index]
return data
print(checkio([3, 3, 5, 8, 1, 4, 5, 2, 4, 4, 3, 0]))
[3, 3, 5, 4, 5, 4, 4, 3]
print(checkio([1, 2, 3, 4]))
[]
This works, because it only deletes numbers in the section of the list that has already been iterated over.
Just I used list Comprehensions.
def checkio(data):
a=[i for i in data if data.count(i)>1]
return a
print checkio([1,1,2,2,1,1,1,3,4,5,6,7,8])
You can implement a OrderedCounter, eg:
from collections import OrderedDict, Counter
class OrderedCounter(Counter, OrderedDict):
pass
data = [1, 3, 1, 2, 3, 5, 8, 1, 5, 2]
duplicates = [k for k, v in OrderedCounter(data).items() if v > 1]
# [1, 3, 2, 5]
So you count the occurrence of each value, then filter on if it has a frequency of more than one. Inheriting from OrderedDict means the order of the original elements is preserved.
Going by comments, you want all duplicated elements reserved, so you can pre-build a set of the duplicate entries, then re-iterate your original list, eg:
from collections import Counter
data = [1, 3, 1, 2, 3, 5, 8, 1, 5, 2]
duplicates = {k for k, v in Counter(data).items() if v > 1}
result = [el for el in data if el in duplicates]
# [1, 3, 1, 2, 3, 5, 1, 5, 2]
Try this:
>>> a=[1,2,3,3,4,5,6,6,7,8,9,2,0,0]
>>> a=[i for i in a if a.count(i)>1]
>>> a
[2, 3, 3, 6, 6, 2, 0, 0]
>>> a=[1, 2, 3, 1, 3]
>>> a=[i for i in a if a.count(i)>1]
>>> a
[1, 3, 1, 3]
>>> a=[1, 2, 3, 4, 5]
>>> a=[i for i in a if a.count(i)>1]
a
[]
def checkio(data):
lis = []
for i in data:
if data.count(i)>1:
lis.append(i)
print(lis)
checkio([1,2,3,3,2,1])
Yeah it's a bit late to contribute to this thread but just wanted to put it there on the net for anyone else use.
Following what you have started, iterating on the list of integers, but not counting or deleting elements, try just testing if the element has already been seen, append it to a list of duplicated elements:
def checkio(data):
elements = []
duplicates = []
for i in data:
if i not in elements:
elements.append(i)
else:
if i not in duplicates:
duplicates.append(i)
return duplicates
d = [1, 3, 1, 2, 3, 5, 8, 1, 5, 2]
print (checkio(d))
#[1, 3, 5, 2]
numbers = [1, 1, 1, 1, 3, 4, 9, 0, 1, 1, 1]
x=set(numbers)
print(x)
You can use the set key word too to get the desired solution.
I used an integer and bool to check every time the list was modified within a while loop.
rechecks = 1
runscan = True
while runscan == True:
for i in data:
if data.count(i) <2:
data.remove(i)
rechecks+=1
#need to double check now
if rechecks >0:
runscan = True
rechecks-=1
else:
runscan = False
return data
Would it not be easier to generate a new list?
def unique_list(lst):
new_list = []
for value in lst:
if value not in new_list:
new_list.append(value)
return new_list
lst = [1,2,3,1,4,5,1,6,2,3,7,8,9]
print(unique_list(lst))
Prints [1,2,3,4,5,6,7,8,9]

remove duplicate element from a list, but only those who has odd number of duplicates

I am trying remove duplicate elements from the list, whose number of duplicates is odd.
For example for the following list: [1, 2, 3, 3, 3, 5, 8, 1, 8] I have 1 duplicated 2 times, 3 duplicated 3 times, and 8 duplicated 2 times. So 1 and 8 should be out and instead of 3 elements of 3 I need to leave only 1.
This is what I came up with:
def remove_odd_duplicates(arr):
h = {}
for i in arr:
if i in h:
h[i] += 1
else:
h[i] = 1
arr = []
for i in h:
if h[i] % 2:
arr.append(i)
return arr
It returns everything correctly: [2, 3, 5], but I do believe that this can be written in a nicer way. Any ideas?
You can use collections.Counter and list comprehension, like this
data = [1, 2, 3, 3, 3, 5, 8, 1, 8]
from collections import Counter
print [item for item, count in Counter(data).items() if count % 2]
# [2, 3, 5]
The Counter gives a dictionary, with every element in the input iterable as the keys and their corresponding counts as the values. So, we iterate over that dict and check if the count is odd and filter only those items out.
Note: The complexity of this solution is still O(N), just like your original program.
If order doesn't matter:
>>> a = [1, 2, 3, 3, 3, 5, 8, 1, 8]
>>> list(set([x for x in a if a.count(x)%2 == 1]))
[2, 3, 5]
The list comprehension [x for x in a if a.count(x)%2 == 1] returns only the elements which appear an odd number of times in the list. list(set(...)) is a common way of removing duplicate entries from a list.
you can possibly use scipy.stats.itemfreq:
>>> from scipy.stats import itemfreq
>>> xs = [1, 2, 3, 3, 3, 5, 8, 1, 8]
>>> ifreq = itemfreq(xs)
>>> ifreq
array([[1, 2],
[2, 1],
[3, 3],
[5, 1],
[8, 2]])
>>> i = ifreq[:, 1] % 2 != 0
>>> ifreq[i, 0]
array([2, 3, 5])

Categories