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]
Related
I have a few lists I'm trying to investigate.I'm stuck at some point:
D = [1, 1, 1, 2, 5, 1, 1, 1, 1, 1, 3, 2, 1, 1]
Let's say this is the list. I need to isolate a new list from the list D.We can say I want to filter those "1"'s; but I couldn't manage it.
If I use "index" method like:
D = [1, 1, 1, 2, 5, 1, 1, 1, 1, 1, 3, 2, 1, 1]
E = []
for i in D:
if not i == 1:
E.append(D.index(i))
print(E)
The output is: [3, 4, 10, 3].What I need is [3, 4, 10, 11].Since values are at D[3] and D[11] are the same, python does not allow me to get the second one.How can I solve this?
Your help is highly appreciated.
Thanks.
You can write this program in many ways. I will try to adapt your example with minimal changes first:
D = [1, 1, 1, 2, 5, 1, 1, 1, 1, 1, 3, 2, 1, 1]
E = []
for i in range(len(D)):
if D[i] != 1:
E.append(i)
print(E)
However, there is also a shorter/simpler one-line solution:
D = [1, 1, 1, 2, 5, 1, 1, 1, 1, 1, 3, 2, 1, 1]
E = [i for i in range(len(D)) if D[i]!=1]
print(E)
You can use a conditional list comprehension to enumerate the values in D and get the index locations of those values that match your condition.
>>> [idx for idx, val in enumerate(D) if val != 1]
[3, 4, 10, 11]
Note that you can also use filter to create a generator of the values at those index locations.
>>> list(filter(lambda val: val != 1, D))
[2, 5, 3, 2]
Using the index function indeed always returns the first occurence. From the documentation:
list.index(x[, start[, end]])
Return zero-based index in the list of the first item whose value is equal to x. Raises a ValueError if there is no such item.
...
We can use list comprehensions and combine this with enumerate to get what you want:
[index for index, value in enumerate(D) if value != 1]
# [3, 4, 10, 11]
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]
Here I have a list
a = [1, 2, 1, 4, 5, 7, 8, 4, 6]
Now I want a following output but without for loop.
Remove all the duplicate from the list.
[2, 5, 7, 8, 6]
output list contain only single occurrence number
Given: a = [1, 2, 1, 4, 5, 7, 8, 4, 6]
One liner:
b = [x for x in a if a.count(x) == 1]
You can use a Counter and a conditional list comprehension or filter in order to maintain the original order:
from collections import Counter
c = Counter(a)
clean_a = filter(lambda x: c[x] == 1, a) # avoids 'for' ;-)
# clean_a = list(filter(lambda x: c[x] == 1, a)) # Python3, if you need a list
# clean_a = [x for x in a if c[a] == 1] # would be my choice
This is a very simple and inefficient implementation.
We use a while loop to access every element of a. In the loop we check if the current element appears only once in the list. If yes, we add it to a new list.
a = [1, 2, 1, 4, 5, 7, 8, 4, 6]
index = 0
result = []
while index < len(a):
if a.count(a[index]) == 1:
result.append(a[index])
index += 1
print(result)
def cleaner(LIST, pos):
if len(LIST)>pos:
if LIST[pos] in LIST[pos+1:]:
LIST.pop(pos)
# OR
# LIST.remove(LIST[pos])
cleaner(LIST, pos)
else:
pos+=1
cleaner(LIST, pos)
return LIST
LIST = [1, 2, 1, 4, 5, 7, 8, 4, 6]
print(cleaner(LIST, 0))
I want my program to take a list that is already created, go through it and check for any elements that repeat. Then create a new list with just the elements that repeat.
def repeated_elements(data):
repeats = []
for element in data:
result = data.count(element)
if result > 1:
repeats.append(element)
return data
print (repeated_elements([1, 2, 3, 1, 3]))#should print out [1, 3, 1, 3]
print (repeated_elements([1, 2, 3, 4, 5]))# should print out []
print (repeated_elements([5, 5, 5, 5, 5]))# should print out [5, 5, 5, 5, 5]
print (repeated_elements([10, 9, 10, 10, 9, 8]))# should print out [10, 9, 10, 10, 9]
The program ends up printing out the starting sets
Better way to achieve this via using collections.Counter with list comprehension expression as:
>>> from collections import Counter
>>> my_list = [1, 2, 3, 1, 3]
>>> my_counter = Counter(my_list)
>>> [i for i in my_list if my_counter[i]>1]
[1, 3, 1, 3]
First of all, you are returning data instead of repeats so it ends up printing out the starting set.
Second - your indentation of the return statement inside the for loop will return the result in the first iteration of the loop. If you fix that, the code will work.
def repeated_elements(data):
repeats = []
for element in data:
result = data.count(element)
if result > 1:
repeats.append(element)
return repeats
How about:
>>> lst = [1, 2, 3, 1, 3]
>>> repeated = [i for i in lst if lst.count(i) > 1]
[1, 3, 1, 3]
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])