find the first unique element in the integer list : python - python

def findFirstUnique(lst):
# Write your code here
for x in lst:
print ('x is:{} '.format(x))
lst.remove(x)
print lst
if x not in lst:
return x
print ('final output is : {}'.format(findFirstUnique(lst)))
Apparently it seems to go through for certain cases like this: [9, 2, 3, 2, 6, 6, 9]
And for some other cases, the for loop seems to behave so weirdly: [4, 5, 1, 2, 0, 4]
and the output for the second case :
x is:4 [5, 1, 2, 0, 4]
x is:1 >>> Why is it not picking "5" as the next value?? [5, 2, 0, 4] final output is : 1
I am kinda losing it now that I am not able to understand this for loop!
Any help would be appreciated.

It is a different approach but it will return the first unique in the list
def findFirstUnique(lst):
for x in lst:
if lst.count(x) == 1:
return x
return None

This should suffice, it is succinct and fast.
[*filter(lambda x: lst.count(x) == 1, lst)][0]
Data:
lst = [9, 2, 3, 1, 2, 6, 6, 9]

In terms of speed, any solution which requires looping over the list for each element in order to check the number of counts (whether as an explicit loop or by using lst.count()) is going to scale as O(n^2) in the worst case. If you start by making a dictionary of counts, and then use the dictionary lookup for each item to check its count, then this should be not much worse than O(n). The code to obtain the counts in pure Python is not particularly difficult, but in fact collections.Counter in the standard library will do it for us, so we may as well use that:
from collections import Counter
def findFirstUnique(lst):
counts = Counter(lst)
for x in lst:
if counts[x] == 1:
return x
else:
return None
if __name__ == '__main__':
lst = [9,2,3,2,6,6,9]
print(findFirstUnique(lst))

The for loop actually iterates the list using the element's index (say i). At the 2nd loop, i=1, lst=[5, 1, 2, 0, 4]. So, the current element is 1, not 5. As a rule, you should not remove or insert any element while iterating.
def findFirstUnique(lst):
for i, x in enumerate(lst):
print('x is:{} '.format(x))
print(lst[:i]+lst[i+1:])
if x not in lst[:i]+lst[i+1:]:
return x
print(findFirstUnique([4, 5, 1, 2, 0, 4]))

Related

Difference Between two list of list [duplicate]

So heres my code:
item = [0,1,2,3,4,5,6,7,8,9]
z = [] # list of integers
for item in z:
if item not in z:
print item
z contains a list of integers. I want to compare item to z and print out the numbers that are not in z when compared to item.
I can print the elements that are in z when compared not item, but when I try and do the opposite using the code above nothing prints.
Any help?
Your code is not doing what I think you think it is doing. The line for item in z: will iterate through z, each time making item equal to one single element of z. The original item list is therefore overwritten before you've done anything with it.
I think you want something like this:
item = [0,1,2,3,4,5,6,7,8,9]
for element in item:
if element not in z:
print(element)
But you could easily do this like:
[x for x in item if x not in z]
or (if you don't mind losing duplicates of non-unique elements):
set(item) - set(z)
>> items = [1,2,3,4]
>> Z = [3,4,5,6]
>> print list(set(items)-set(Z))
[1, 2]
Using list comprehension:
print [x for x in item if x not in Z]
or using filter function :
filter(lambda x: x not in Z, item)
Using set in any form may create a bug if the list being checked contains non-unique elements, e.g.:
print item
Out[39]: [0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print Z
Out[40]: [3, 4, 5, 6]
set(item) - set(Z)
Out[41]: {0, 1, 2, 7, 8, 9}
vs list comprehension as above
print [x for x in item if x not in Z]
Out[38]: [0, 1, 1, 2, 7, 8, 9]
or filter function:
filter(lambda x: x not in Z, item)
Out[38]: [0, 1, 1, 2, 7, 8, 9]
list1 = [1,2,3,4]; list2 = [0,3,3,6]
print set(list2) - set(list1)
If you run a loop taking items from z, how do you expect them not to be in z? IMHO it would make more sense comparing items from a different list to z.
No, z is undefined. item contains a list of integers.
I think what you're trying to do is this:
#z defined elsewhere
item = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for i in item:
if i not in z: print i
As has been stated in other answers, you may want to try using sets.
>>> item = set([0,1,2,3,4,5,6,7,8,9])
>>> z = set([2,3,4])
>>> print item - z
set([0, 1, 5, 6, 7, 8, 9])
Your code is a no-op. By the definition of the loop, "item" has to be in Z. A "For ... in" loop in Python means "Loop though the list called 'z', each time you loop, give me the next item in the list, and call it 'item'"
http://docs.python.org/tutorial/controlflow.html#for-statements
I think your confusion arises from the fact that you're using the variable name "item" twice, to mean two different things.
You are reassigning item to the values in z as you iterate through z. So the first time in your for loop, item = 0, next item = 1, etc... You are never checking one list against the other.
To do it very explicitly:
>>> item = [0,1,2,3,4,5,6,7,8,9]
>>> z = [0,1,2,3,4,5,6,7]
>>>
>>> for elem in item:
... if elem not in z:
... print elem
...
8
9
In the case where item and z are sorted iterators, we can reduce the complexity from O(n^2) to O(n+m) by doing this
def iexclude(sorted_iterator, exclude_sorted_iterator):
next_val = next(exclude_sorted_iterator)
for item in sorted_iterator:
try:
while next_val < item:
next_val = next(exclude_sorted_iterator)
continue
if item == next_val:
continue
except StopIteration:
pass
yield item
If the two are iterators, we also have the opportunity to reduce the memory footprint not storing z (exclude_sorted_iterator) as a list.
If the lists are sorted and you know the elements of the checking list are in the base list - you can do a more optimal O(n) solution by using two pointers (where n will be the length of the base_list:
base_list = [0, 1, 2, 3, 4, 5, 6, 7, 8]
checking_list = [1, 3, 5]
expected_return = [0, 2, 4, 6, 7, 8]
j = 0
i = 0
elements_not_in_checking_list = []
while i < len(base_list):
if j < len(checking_list) and base_list[i] == checking_list[j]:
i += 1
j += 1
else:
elements_not_in_checking_list.append(base_list[i])
i += 1
Many of the solutions already posted here will not preserve the original ordering of the elements (because sets are unordered) or are inefficient (because linear search in a list is slower than a lookup in a set).
You can make a set of elements to remove upfront, and then use a list comprehension to retain only the elements which aren't in the set:
items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
z = [3, 4, 5, 6]
set_z = set(z)
result = [e for e in items if e not in set_z]
Then, result contains:
[0, 1, 2, 7, 8, 9]

How to find a greedy solution in a list with duplicates

I am trying to solve a sequencing/scheduling problem. In this work I have encountered a problem regarding finding a greedy solution for a sequence with duplicates.
My initial sequence looks like this: [2, 9, 4, 11, 11] (or can be similar, containing duplicates).
My algorithm will select an arbitrary/random number of the sequence as its first element and then further pick the elements of lowest value as the following elements.
The code I have proposed is as follows:
l = [2, 9, 4, 11, 11]
t=l.copy()
seq = [random.randint(0,N-1)]
i = 0
while i < N:
a = min(t)
if seq[0] == i:
i +=1
else:
seq.append(l.index(a))
t.remove(t[t.index(a)])
i+=1
print(seq)
One example of a solution from this code is: [3, 0, 2, 1, 3], which is not desired as I want it to be [1, 0, 2, 1, 4].
Thanks for the help!
Now the problem is clear: you're trying to return a list of the indices to the integers in its sorted rising order. I have a solution for that.
def sort(lst):
# Make 2d array containing elements and their index
pairs = [[num,ind] for ind, num in enumerate(lst)]
sorted_indices = []
# Go through sorted pairs and collect indices into sorted_indices
for pair in sorted(pairs):
sorted_indices.append(pair[1])
return sorted_indices
Test:
sort([2, 1, 3, 1])
Output:
[1, 3, 0, 2]

Appending a list through if condition in python

This could be a very basic question, but I realized I am not understanding something.
When appending new things in for loop, how can I raise conditions and still append the item?
For instance:
alist = [0,1,2,3,4,5]
new = []
for n in alist:
if n == 5:
continue
else:
new.append(n+1)
print(new)
Gets me
[1, 2, 3, 4, 5]
How do I get
[1, 2, 3, 4, 5, 5] # 4 is incremented, 5 is added 'as is'
Essentially, I want to tell python to not go through n+1 when n==5.
Would this be the only solution? append n==5 separately in a list and then sum new and the separate list?
Why don't you just append the 5 instead of using continue, is there any other condition?
for n in alist:
if n == 5:
new.append(n)
else:
new.append(n+1)
You can use the fact the a boolean True is 1 while a False is 0 combined with a list comprehension like:
Code:
[x + int(i != 5) for i, x in enumerate(alist)]
Test Code:
alist = [0, 1, 2, 3, 4, 5]
new = [x + int(i != 5) for i, x in enumerate(alist)]
print(new)
Result:
[1, 2, 3, 4, 5, 5]
Seems like you didn't get the point of 'continue'. The Python keyword 'continue', means you do nothing in that if condition, so basically you tell the program "do nothing" when n == 5 and if n is not 5, you do some operation. That's why you got your original result. Hope it may help.

How to append to new list item when checking list with for loop?

I am having problems with this and can't figure out why my code is not working. Could someone help me out with this, please? I made this:
def f8(a_list, n):
"""
The parameter a_list is a list of int's. The parameter n is an int.
The function f8() should return a list that contains exactly one
of each number in a_list that occurs less than n times in a_list.
Example:
f8([1, 1, 7, 7, 7, 3, 3, 3, 4, 4, 4, 5, 5], 3) should return
[1, 5] (as 1 and 5 are the only numbers that occur less than 3
times in a_list)
"""
k = []
for i in a_list:
if i < a_list.count(n):
k.append(i)
return k
print f8([1, 7, 7, 3, 3, 3, 4, 4, 5], 2)
I would expect it should print [1,5], but it just gives me a None. Why is that? Could someone help me out, please? I am stuck here.
You have the counting the wrong way around! You need to count the occurrences of i and compare this against n. Also, you need to move the return outside the for-loop. Finally, to remove the repeats in the final list, we should iterate through set(a_list) so that we only iterate through unique elements. The neat thing about this is that since we are counting the occurrences in the original a_list, we don't need to create any copies or anything fiddly to deal with this.
This makes your function:
def f8(a_list, n):
k = []
for i in set(a_list):
if a_list.count(i) < n:
k.append(i)
return k
which works if we give it a test:
>>> f8([1, 1, 7, 7, 7, 3, 3, 3, 4, 4, 4, 5, 5], 3)
[1, 5]
>>> f8([1, 1, 2, 2, 2, 2, 4, 5, 6, 7, 7, 7, 7], 3)
[1, 4, 5, 6]
Note, if you wanted to shorten the function, you could achieve the same result in a one line list-comprehension:
def f8(a_list, n):
return [i for i in set(a_list) if a_list.count(i) < n]
which gives the same outputs to the tests as above.
Firstly, you should not call count repeatedly. Each call iterates the entire list. You can get all counts in one go using collections.Counter. Secondly, you need to check if you have added any element before to avoid duplicates, just calling set one a_list will not guarantee order of appearance:
from collections import Counter
def f8(a_list, n):
c = Counter(a_list)
k, seen = [], set()
for x in a_list:
if c[x] < n and x not in seen:
seen.add(x)
k.append(x)
return k
The condition to append in your code is never met, thus, no value is being returned. Instead, return after the loop is finished. Also, your counting condition is reversed, as you should be finding the count of i occurring in the list, not n:
k = []
for i in a_list:
if a_list.count(i) < n and i not in k:
k.append(i)
return k
The reason why you are receiving None is that the return statement does not pass, so to satisfy the variable storage during the function call, None is returned.

Finding elements not in a list

So heres my code:
item = [0,1,2,3,4,5,6,7,8,9]
z = [] # list of integers
for item in z:
if item not in z:
print item
z contains a list of integers. I want to compare item to z and print out the numbers that are not in z when compared to item.
I can print the elements that are in z when compared not item, but when I try and do the opposite using the code above nothing prints.
Any help?
Your code is not doing what I think you think it is doing. The line for item in z: will iterate through z, each time making item equal to one single element of z. The original item list is therefore overwritten before you've done anything with it.
I think you want something like this:
item = [0,1,2,3,4,5,6,7,8,9]
for element in item:
if element not in z:
print(element)
But you could easily do this like:
[x for x in item if x not in z]
or (if you don't mind losing duplicates of non-unique elements):
set(item) - set(z)
>> items = [1,2,3,4]
>> Z = [3,4,5,6]
>> print list(set(items)-set(Z))
[1, 2]
Using list comprehension:
print [x for x in item if x not in Z]
or using filter function :
filter(lambda x: x not in Z, item)
Using set in any form may create a bug if the list being checked contains non-unique elements, e.g.:
print item
Out[39]: [0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print Z
Out[40]: [3, 4, 5, 6]
set(item) - set(Z)
Out[41]: {0, 1, 2, 7, 8, 9}
vs list comprehension as above
print [x for x in item if x not in Z]
Out[38]: [0, 1, 1, 2, 7, 8, 9]
or filter function:
filter(lambda x: x not in Z, item)
Out[38]: [0, 1, 1, 2, 7, 8, 9]
list1 = [1,2,3,4]; list2 = [0,3,3,6]
print set(list2) - set(list1)
If you run a loop taking items from z, how do you expect them not to be in z? IMHO it would make more sense comparing items from a different list to z.
No, z is undefined. item contains a list of integers.
I think what you're trying to do is this:
#z defined elsewhere
item = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for i in item:
if i not in z: print i
As has been stated in other answers, you may want to try using sets.
>>> item = set([0,1,2,3,4,5,6,7,8,9])
>>> z = set([2,3,4])
>>> print item - z
set([0, 1, 5, 6, 7, 8, 9])
Your code is a no-op. By the definition of the loop, "item" has to be in Z. A "For ... in" loop in Python means "Loop though the list called 'z', each time you loop, give me the next item in the list, and call it 'item'"
http://docs.python.org/tutorial/controlflow.html#for-statements
I think your confusion arises from the fact that you're using the variable name "item" twice, to mean two different things.
You are reassigning item to the values in z as you iterate through z. So the first time in your for loop, item = 0, next item = 1, etc... You are never checking one list against the other.
To do it very explicitly:
>>> item = [0,1,2,3,4,5,6,7,8,9]
>>> z = [0,1,2,3,4,5,6,7]
>>>
>>> for elem in item:
... if elem not in z:
... print elem
...
8
9
In the case where item and z are sorted iterators, we can reduce the complexity from O(n^2) to O(n+m) by doing this
def iexclude(sorted_iterator, exclude_sorted_iterator):
next_val = next(exclude_sorted_iterator)
for item in sorted_iterator:
try:
while next_val < item:
next_val = next(exclude_sorted_iterator)
continue
if item == next_val:
continue
except StopIteration:
pass
yield item
If the two are iterators, we also have the opportunity to reduce the memory footprint not storing z (exclude_sorted_iterator) as a list.
If the lists are sorted and you know the elements of the checking list are in the base list - you can do a more optimal O(n) solution by using two pointers (where n will be the length of the base_list:
base_list = [0, 1, 2, 3, 4, 5, 6, 7, 8]
checking_list = [1, 3, 5]
expected_return = [0, 2, 4, 6, 7, 8]
j = 0
i = 0
elements_not_in_checking_list = []
while i < len(base_list):
if j < len(checking_list) and base_list[i] == checking_list[j]:
i += 1
j += 1
else:
elements_not_in_checking_list.append(base_list[i])
i += 1
Many of the solutions already posted here will not preserve the original ordering of the elements (because sets are unordered) or are inefficient (because linear search in a list is slower than a lookup in a set).
You can make a set of elements to remove upfront, and then use a list comprehension to retain only the elements which aren't in the set:
items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
z = [3, 4, 5, 6]
set_z = set(z)
result = [e for e in items if e not in set_z]
Then, result contains:
[0, 1, 2, 7, 8, 9]

Categories