Simple way to remove duplicate item in a list [duplicate] - python-3.x

This question already has answers here:
How do I remove duplicates from a list, while preserving order?
(30 answers)
Closed 4 years ago.
the program says "TypeError: 'int' object is not iterable"
list=[3,3,2]
print(list)
k=0
for i in list:
for l in list:
if(l>i):
k=l
for j in k:
if(i==j):
del list[i]
print(list)

An easy way to do this is with np.unique.
l=[3,3,2]
print(np.unique(l))
Hope that helps!
Without using any numpy the easiest way I can think of is to start with a new list and then loop through the old list and append the values to the new list that are new. You can cheaply keep track of what has already been used with a set.
def delete_duplicates(old_list):
used = set()
new_list= []
for i in old_list:
if i not in used:
used.add(i)
new_list.append(i)
return new_list
Also, a couple tips on your code. You are getting a TypeError from the for j in k line, it should be for j in range(k). k is just an integer so you can't iterate over it, but range(k) creates an iterable that will do what you want.

Just build another list
>>> list1=[3,2,3]
>>> list2=[]
>>> for i in list1:
... if i in list2:
... pass
... else:
... list2.append(i)
...
>>> list2
[3, 2]
You can always add list1 = list2 at the end if you prefer.

You can use set()
t = [3, 3, 2]
print(t) # prints [3, 3, 2]
t = list(set(t))
print(t) # prints [2, 3]

To remove a duplicate item in a list and get list with unique element, you can always use set() like below:
example:
>>>list1 = [1,1,2,2,3,3,3]
>>>new_unique_list = list(set(list1))
>>> new_unique_list
>>>[1, 2, 3]

You have the following line in your code which produces the error:
for j in k:
k is an int and cannot be iterated over. You probably meant to write for j in list.
There are a couple good answers already. If you really want to write the code yourself however, I'd recommend functional style instead of working in place (i.e. modifying the original array). For example like the following function which is basically a port of Haskell's Data.List.nub.
def nub(list):
'''
Remove duplicate elements from a list.
Singleton lists and empty lists cannot contain duplicates and are therefore returned immediately.
For lists with length gte to two split into head and tail, filter the head from the tail list and then recurse on the filtered list.
'''
if len(list) <= 1: return list
else:
head, *tail = list
return [head] + nub([i for i in tail if i != head])
This is—in my opinion—easier to read and saves you the trouble associated with multiple iteration indexes (since you create a new list).

Related

How to subtract adjacent items in list with unknown length (python)?

Provided with a list of lists. Here's an example myList =[[70,83,90],[19,25,30]], return a list of lists which contains the difference between the elements. An example of the result would be[[13,7],[6,5]]. The absolute value of (70-83), (83-90), (19-25), and (25-30) is what is returned. I'm not sure how to iterate through the list to subtract adjacent elements without already knowing the length of the list. So far I have just separated the list of lists into two separate lists.
list_one = myList[0]
list_two = myList[1]
Please let me know what you would recommend, thank you!
A custom generator can return two adjacent items at a time from a sequence without knowing the length:
def two(sequence):
i = iter(sequence)
a = next(i)
for b in i:
yield a,b
a = b
original = [[70,83,90],[19,25,30]]
result = [[abs(a-b) for a,b in two(sequence)]
for sequence in original]
print(result)
[[13, 7], [6, 5]]
Well, for each list, you can simply get its number of elements like this:
res = []
for my_list in list_of_lists:
res.append([])
for i in range(len(my_list) - 1):
# Do some stuff
You can then add the results you want to res[-1].

The best way of iterating through an array whose length changes in Python

I am implementing an algorithm which might affect the size of some array, and I need to iterate through the entire array. Basically a 'for x in arrayname' would not work because it does not update if the contents of arrayname are changed in the loop. I came up with an ugly solution which is shown in the following example:
test = np.array([1,2,3])
N = len(test)
ii=0
while ii < N:
N = len(test)
print(test[ii])
if test[ii] ==2:
test = np.append(test,4)
ii+=1
I am wondering whether a cleaner solution exists.
Thanks in advance!
Assuming all the elements are going to be added at the end and no elements are being deleted you could store the new elements in a separate list:
master_list = [1,2,3]
curr_elems = master_list
while len(curr_elems) > 0: # keep looping over new elements added
new_elems = []
for item in curr_elems: # loop over the current list of elements, initially the list but then all the added elements on second run etc
if should_add_element(item):
new_elems.append(generate_new_element(item))
master_list.extend(new_elems) # add all the new elements to our master list
curr_elems = new_elems # and prep to iterate over the new elements for next iteration of the while loop
The while loop seems the best solution. As the condition is re-evaluated at each iteration, you don’t need to reset the length of the list in the loop, you can do it inside the condition:
import random
l = [1, 2, 3, 4, 5]
i = 0
while i < len(l):
if random.choice([True, False]):
del l[i]
else:
i += 1
print(f'{l=}')
This example gives a blueprint for a more complex algorithm. Of course, in this simple case, it could be coded more simply with a filter, or like this:
l = [1, 2, 3, 4, 5]
[x for x in l if random.choice([True, False])]
You might want to check this related post for more creative solutions: How to remove items from a list while iterating?

Is there a python function to get all indexes from unique values?

I know there are methods like set() or np.unqiue() to get unique values from lists. But I search for a way to get the index for the value which occurs not more than one time.
example = [0,1,1,2,3,3,4]
what I looking for is
desired_index_list = [0,3,6]
Any suggestions?
Don't know of any prebuilt solution, probably you need to create your own. There are different approaches for that, but with classical Python implementation, you can easily create a count_dict and filter those values from the original list that have count of 1.
>>> from collections import Counter
>>> example = [0,1,1,2,3,3,4]
>>> counted = Counter(example)
>>> desired_index_list = [index for index, elem in enumerate(example) if counted[elem] == 1]
>>> desired_index_list
[0, 3, 6]
You can do this as a one-liner with a list comprehension:
from collections import Counter
[example.index(x) for x, y in Counter(example).items() if y == 1]
(Using Counter, return tuples for each item (x) and its number of occurrence (y), and return the index of the item if it's count is 1).

This for circle cannot delete every same elements in a list, I don't know why [duplicate]

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 4 years ago.
a = [1, 2, 2]
value = 2
for i in a:
if i == value:
a.remove(i)
I want to delete 2 same elements in a list. But the result tells me I just delete one of them. when I debug it, I find it only cycle 2 times, not 3 as I wish.
You can use a simple list comprehension for a 1-line solution:
In [2764]: a = [1, 2, 2]
In [2755]: value = 2
In [2768]: a = [i for i in a if i != value]
In [2769]: a
Out[2769]: [1]
You can write the above as :
ans = []
for i in a:
if i <> value:
ans.append(i)
OR, you can also use filter to remove all occurrences:
Python-2
In [2778]: filter(lambda x: x!= value, a)
Out[2778]: [1]
Python-3
In [5]: list(filter(lambda x: x!= value, a))
Out[5]: [1]
Here you don't have to use a comparison to remove a certain value from list
Here is a little modification to your code:
a = [1, 2, 2]
value = 2
try:
for i in a: a.remove (value)
except ValueError: pass
print (a)
Whenever the remove () function couldn't find the value you are looking for, it will raise a value error: ValueError: list.remove(x): x not in list. To eliminate this, surround it with a try except. That'll do the trick.
However there are more easier methods to use remove () function. For an example you could use while loop.
Look at this code:
a = [1, 2, 2]
value = 2
while value in a:
a.remove (value)
print (a)
Its far more easier.

Python list comprehension - conditional for-loop

I've written some code like so which works fine and does what I want:
#!/usr/bin/env python3
myList = [[0], [1, 2], {'val': [3, 4, 5]}, [6]]
flat1 = []
for sublist in myList:
if type(sublist) is list:
for item in sublist:
flat1.append(item)
else:
for item in sublist['val']:
flat1.append(item)
print(flat1)
So it's a twist on the standard nested list flattening. The twist is that some nested items are not actually lists, but rather dictionaries with a 'val' (and we want the items in the 'val' list in those cases).
I'm trying to make it into a list comprehension. Here is what I've tried:
flat2 = [item for sublist in myList for item in sublist if type(sublist) is list else for item in sublist['val']]
print(flat2)
I get the following error with a caret pointing to the 'else'.
SyntaxError: invalid syntax
And yes what I've written into the list comprehension seems like nonsense and no doubt the compiler has no idea what I'm trying to do.
Is it possible to do what I'm trying to do with a list comprehension?
[item
for sublist in myList
for item in (sublist if type(sublist) is list else sublist['val'])
]
First off, I recommend against this approach. Why do you want to take what is already pretty readable and condense it so that it's unreadable?
flattened = [i for iterable in
(j if type(j) is list else j["val"] for j in myList)
for i in iterable]
Update after reading comment
One nice thing to do is to break out the list comprehension into two steps:
iterables = (j if type(j) is list else j["val"] for j in myList)
flattened = [i for iterable in iterables for i in iterable]
This is more readable -- and no less computationally efficient. Note the use of parentheses in iterables -- which makes it a generator that is lazily evaluated. That way, if myList is really long, you're still only reading through it once and you don't have to wait to read all the way through before proceeding.

Resources