Python programming about list [duplicate] - python

This question already has answers here:
Removing duplicates in lists
(56 answers)
Closed 6 years ago.
In this program I want to remove the duplicate values from the list. This is what i wrote:
list = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
def loop():
for a in range(len(list)-1):
for b in range(a+1,len(list)):
if list[a] == list[b]:
del list[a]
print(list)
loop()
But, it's giving me this error:
Can you help me?

If you have numpy then you can do (I renamed your list to l to avoid ambiguity):
import numpy as np
l = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
l_no_duplicates = list( np.unique(l) )

The common approach to get a unique collection of items is to use a set. Sets are unordered collections of distinct objects.
list = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
newList = list(set(list))
[1, 2, 3, 5, 8, 13, 34, 21, 55, 89]

Do something like the following:
create new_list
for item in list:
if item not in new_list:
add item to new_list
list = new_list
In Python:
list = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
print list
new_list = []
for item in list:
if item not in new_list:
new_list.append(item)
list = new_list
print list
Now run python filename.py and you will see the difference between two lists.

Related

a = set(list()) elements are changing in order, even though it has distinct elements [duplicate]

This question already has answers here:
How do I remove duplicates from a list, while preserving order?
(30 answers)
Closed 6 months ago.
a = [0, 22, 2, 3, 44, 5, 6, 27, 8, 19]
print(a)
print(set(a))
but I need it like this
output:
[0, 22, 2, 3, 44, 5, 6, 27, 8, 19]
{0, 2, 3, 5, 6, 8, 44, 19, 22, 27}
for getting this kind of output I can use list with for.. too with bellow cade or by method ( removing duplicates from list ).. there are many ways.. but
lis = []
for i in a:
if i in lis:
lis.append(i)
print(lis)
output:
[0, 22, 2, 3, 44, 5, 6, 27, 8, 19]
but the thing is I need to get this kind of output in set function, and give me the reason why it is changing in order.. or who this transformation workes ???
This is covered in the Python documentation. A set uses a hash-table structure internally to make for faster lookups. Enumerating that table does not retain the insertion order.
You can do this with a dict, which does happen to retain insertion order in Python 3.6 and beyond.
a = list(dict((i,1) for i in a))

Python3: Reverse a list using only while, .pop() and .insert()

I am trying to do the following exercise:
Challenge: reverse a list using while .pop() insert() pop() the first item in the list and add to the beginning of a new string that will be reversed
some_numbers =[1,2,3,4,5,6,7,8,9,11,22,33,44,55,66,77]
Here's the code I have written:
some_numbers =[1,2,3,4,5,6,7,8,9,11,22,33,44,55,66,77]
new=[]
while some_numbers:
x=some_numbers.pop() #Should delete the last item on the list
new.insert(-1,x) #Should insert it in -1 position on the list
print(new)
However, this is the result I am getting:
[66, 55, 44, 33, 22, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1, 77]
Does somebody know how can I make the "77" at the beginning on the list? I tried populating new=[" "] and it works but obviously the space appears as part of the list in the result and I just want the numbers there. Thanks!!
Try inserting at len(reverse):
some_numbers =[1,2,3,4,5,6,7,8,9,11,22,33,44,55,66,77]
reverse = []
while some_numbers:
reverse.insert(len(reverse), some_numbers.pop())
print(reverse)
Output
[77, 66, 55, 44, 33, 22, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1]
From the documentation:
Insert an item at a given position. The first argument is the index of
the element before which to insert, so a.insert(0, x) inserts at the
front of the list, and a.insert(len(a), x) is equivalent to
a.append(x).
Notice that:
The first argument is the index of the element before which to
insert
When you do insert(-1, x), your code inserts before the last element, for example if you print reverse at each stage, you get:
[77]
[66, 77]
[66, 55, 77]
[66, 55, 44, 77]
[66, 55, 44, 33, 77]
[66, 55, 44, 33, 22, 77]
...
You can solove this challenge using with a single variable(i):
some_numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77]
new = []
i = 0
while some_numbers:
x = some_numbers.pop() # Should delete the last item on the list
new.insert(i, x) # Should insert it in -1 position on the list
i += 1
print(new)
Always pop the first item of some_numbers and insert it at the beginning of the new list, which is what the question stated was to be done:
>>> some_numbers = [1,2,3,4,5,6,7,8,9,11,22,33,44,55,66,77]
>>> new = []
>>> while some_numbers:
... new.insert(0, some_numbers.pop(0))
...
>>> new
[77, 66, 55, 44, 33, 22, 11, 9, 8, 7, 6, 5, 4, 3, 2, 1]
>>>
Why the OP's Answer Does Not Work
new.insert(-1, 3) inserts 3 before the last element of new. When new is empty, 3 is just inserted and we have [3] as the result. But subsequent insertions are inserted before the last element, which is 3. Thus, the first element inserted will always be the last element of the final list. In the example below, that will be the number 3:
>>> l = []
>>> l.insert(-1, 3)
>>> l
[3]
>>> l.insert(-1, 2)
>>> l
[2, 3]
>>> l.insert(-1, 1)
>>> l
[2, 1, 3]
>>>
So instead of reversing 1, 2, 3 to get 3, 2, 1, we end up with 2, 1, 3. 3 should have been at the beginning of the final result but it is instead at the end because it was the first item inserted.
Reverse the following list using python without using a list-reversed function. what about this?
List_new=[22 , 33 ,44 ,55 ,66 ,77 ,88]

How do I not get duplicates in this list comprehension?

I am trying to take two lists with different lengths, and trying to make a third list which contains the same numbers using list comprehension. I want to avoid duplicates.
I attempted to use list comprehension with an if test, as I will show in the code. I also attempted an and statement, but that does not work.
a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
c = [x for x in a if x in b]
This is the current solution I have, 'I also tried to alter the c list comprehension to:
c = [x for x in a if x in b and x not in c]
But this did not work. Is this not possible using list comprehension? I am aware that I can do this using sets quite easily. I am just practicing the use of list comprehension.
Depending on your reasons for using a list for c, you could consider using the built-in set structure to do intersection operations and which guarantees uniqueness of elements. For instance, set(a) will produce a set containing the unique elements in a.
c = [x for x in a if x in b] does not work since the duplicate elements in a are still contained in b and therefore not excluded by your if statement. (1 is duplicated in a, but both elements will be contained in c by your first definition, since 1 is in b).
EDIT: if you want to simply modify your list comprehension but continue using it, you could do something like: c = [x for x in set(a) if x in b]
If you want a new list of all elements that appear in either of the 2 original lists, you could use the set class to achieve that. Maybe like this:
>>> a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
>>> list(sorted(set(a) | set(b)))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 21, 34, 55, 89]
What this does is building 2 sets from the lists, then finding the union of all the elements and then convert the result back to a list.
This approach will be faster than checking elem for elem in a if elem in b for large lists, because membership tests are O(1) for sets but up to O(n) for lists.
I will present a slightly different solution: The idea would be to first count the frequency of numbers using Counter and then perform the list comprehension using the keys. Since Counter returns a dictionary, you will not have duplicate keys.
from collections import Counter
a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
f1 = Counter(a)
f2 = Counter(b)
c = [x for x in f1.keys() if x in f2.keys()]
# [1, 2, 3, 5, 8, 13]

how to remove elements of the same type from a list in python [duplicate]

This question already has answers here:
Determine the type of an object? [duplicate]
(15 answers)
Closed 4 years ago.
Let's say I have a list and I want to remove the elements of the same type from it - I tried to do it this way but it is an obvious nonsense:
list = [14, 5, 53, "Mercedes", 5, 66, 5, 4, "BMW", 5, 4, 6, "Tesla", 111, 333, 22, 33, 44]
for each_element in list:
while(type(each_element)) == <int> in list:
list.remove(each_element)
Can anybody give me a hint?
You can do it simpler using list comprehension.
values = [14, 5, 53, "Mercedes", 5, 66, 5, 4, "BMW", 5, 4, 6, "Tesla", 111, 333, 22, 33, 44]
newlist = [value for value in values if type(value) != int]
PS: Don't save list as as variable as it 's a python class

Find Largest Element in 2 Ordered Lists which does not occur in one list

Hi I've searched here but can't find an answer to my problem.
I'm using Python and have 2 lists. They are both ordered. The first list is generally the longer one (approx 10,000 elements) and it never changes. The second one is shorter but grows as the program runs to eventually be the same length.
The lists might look like this:
[1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 8, 8, 10, 11, 12, 13, 16, 18, 19, 20]
[1, 1, 2, 2, 3, 4, 16, 18, 19, 20]
In which case, I want to return 13 because it's the maximum element in list 1 that is not in list 2.
Now I do this repeatedly so list 1 needs to remain unchanged. Both lists contain duplicate values.
My naive way of doing it is far too slow:
def removeItems(list2, list1):
list1Copy = list(list1)
for item in list2:
if item in list1Copy:
list1Copy.remove(item)
return list1Copy
So I just create a new list and then remove all the items that exist in the shorter list and then the value I want is the end value in list1Copy.
There must be a much faster way of doing this using dicts or something?
So far none of the answers that have been given take any advantage of the fact that the lists are ordered and we want the largest value from l1 that is not in l2. Here's an solution that does:
from itertools import zip_longest # note this function is named izip_longest in Python 2
def max_in_l1_not_in_l2(l1, l2):
if len(l1) <= len(l2):
raise ValueError("l2 has at least as many items as l1")
for a, b in zip_longest(reversed(l1), reversed(l2), fillvalue=float("-inf")):
if a > b:
return a
elif a != b:
raise ValueError("l2 has larger items than l1")
raise ValueError("There is no value in l1 that is not in l2") # should never get here
If you can rely upon l2 being a proper subset of l1, you could strip out the error checking. If you distill it down, you'll end up with a very simple loop, which can even become a single expression:
next(a for a, b in zip_longest(reversed(l1), reversed(l2), fillvalue=float("-inf"))
if a > b)
The reason this code will often be faster than other implementations (such as behzad.nouri's good answer using collections.Counter) is that, thanks to the reverse iteration, it can return the result immediately when it comes across a value from l1 which is not in l2 (the first such value it finds will be the largest). Doing a multiset subtraction will always process all the values of both lists, even though we may only need to look at the largest few values.
Here's an example that should be noticeably faster in my code than in any non-short-circuting version:
l1 = list(range(10000000))
l2 = l1[:-1]
print(max_in_l1_not_in_l2(l1, l2)) # prints 9999999
>>> l1 = [1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 8, 8, 10, 11, 12, 13, 16, 18, 19, 20]
>>> l2 = [1, 1, 2, 2, 3, 4, 16, 18, 19, 20]
You can grab a list of all items in l1 that do not occur in l2
>>> filter(lambda i : i not in l2, l1)
[5, 5, 6, 7, 8, 8, 10, 11, 12, 13]
Then take the max of that list
>>> max(filter(lambda i : i not in l2, l1))
13
>>> l1 = [1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 8, 8, 10, 11, 12, 13, 16, 18, 19, 20]
>>> l2 = [1, 1, 2, 2, 3, 4, 16, 18, 19, 20]
>>> max(set(l1) - set(l2))
13
edit:
>>> l1 = [19, 20, 20]
>>> l2 = [19, 20]
>>> from collections import Counter
>>> max(Counter(l1) - Counter(l2))
20
OK, so I've managed to do it:
def findLargestUnknownLength(l1, l2):
l1Index = len(l1) - 1
l2Index = len(l2) - 1
while True:
if l2[l2Index] == l1[l1Index]:
l1Index -= 1
l2Index -=1
elif l2[l2Index] < l1[l1Index]:
return l1[l1Index]
For those wondering, this is part of the solution to The Turnpike Problem. A good description can be found here: Turnpike Walkthrough.
This was a problem on Rosalind.

Categories

Resources