My code:
def shorter(lst):
if len(lst) == 0:
return []
if lst[0] in lst[1:]:
lst.remove(lst[0])
shorter(lst[1:])
return lst
print shorter(["c","g",1,"t",1])
Why does it print ["c","g",1,"t",1] instead of ["c","g","t",1]
For a recursive method, what you can do is check a specific index in the again as you have it. If we remove the current element, we want to stay at the same index, otherwise we want to increase the index by one. The base case for this is if we are looking at or beyond the last element in the array since we don't really need to check it.
def shorter(lst, ind=0):
if ind >= len(lst)-1: #Base Case
return lst
if lst[ind] in lst[ind+1:]:
lst.pop(ind)
return shorter(lst,ind)
return shorter(lst, ind+1)
#Stuff to test the function
import random
x = [random.randint(1,10) for i in range(20)]
print(x)
x = shorter(x)
print(x)
Another way to solve this in a single line is to convert the list into a set and then back into a list. Sets have only unique values, so we can use that property to remove any repeating elements.
import random
x = [random.randint(1,10) for i in range(20)]
print(x)
x = list(set(x)) #Converts to set and back to list
print(x)
A possible recursive solution could be:
def shorter(lst):
if lst:
if lst[0] in lst[1:]:
prefix = [] # Skip repeated item.
else:
prefix = [lst[0]] # Keep unique item.
return prefix + shorter(lst[1:])
else:
return lst
The previous code can also be compacted to:
def shorter(lst):
if lst:
return lst[0:(lst[0] not in lst[1:])] + shorter(lst[1:])
else:
return lst
and the function body can also be reduced to a one-liner:
def shorter(lst):
return (lst[0:(lst[0] not in lst[1:])] + shorter(lst[1:])) if lst else lst
or even:
def shorter(lst):
return lst and (lst[0:(lst[0] not in lst[1:])] + shorter(lst[1:]))
Related
i have two lists
lsitA = [100,200,300]
listB = [[97,103],[103,202],[202,250]]
i'm trying to check if item in listA[x] is within a certain margin from listB[i][0] or listB[i][1]
then return false, else return true. in other words i'm trying to see if lsitA[0] meets these condition either for listB[1] or listB[2] or listB[3], then return False. number of True/False must be equal to number of sub-lists in listB
this is what i have tried so far
lsitA = [100,200,300]
listB = [[97,103],[103,202],[202,250]]
def check(listB, val):
result = []
for x in range(len(listB)):
if listB[x][0]<=val<=listB[x][0]+4 or listB[x][1]-4<=val<=listB[x][1]:
return result.append(print('Fail'))
return result.append(print('Pass'))
for i in lsitA:
check(listB,i)
##Expected output: [Fail,Fail,Pass]
result.append() Returns nothing, and so does print().
If you want a list containing the result, I suggest doing the followings:
def check(listB, val):
for item in listB:
if val in range(item[0], item[1]+1):
return 'Fail'
return 'Pass'
result = [check(listB, i) for i in listA]
I am trying to make a function that is able to find a element in a nested list.
That is what if got so far:
def in_list(ele, lst, place):
if ele == lst[place]:
return True
else:
for i in range(len(lst)):
in_list(ele, lst[i], place)
This is what i input:
a=[[1,2],[3,4]]
if in_list(2,a,1)==True:
print("True")
the variable "place" is the place in the list where the element should be found...
Now somehow it doesn't understand this line if ele == lst[place]
this is the error message: TypeError: 'int' object is not subscriptable
Thanks in advance
There are two issues in the last line
def in_list(ele, lst, place):
if ele == lst[place]:
return True
else:
for i in range(len(lst)):
in_list(ele, lst[i], place)
lst[i] is an integer (assuming lst is a list of integers), which is why you get your error.
The other issue is that you're not returning anything from the else branch.
Something like this might work better in case of arbitrary, but uniform, nesting:
def recursive_contains(item, lst):
if len(lst) == 0:
return False
elif isinstance(lst[0], collections.Iterable):
return any(recursive_contains(item, sublist) for sublist in lst)
else:
return item in lst
for arbitrary non-uniform nesting, perhaps something like this:
def recursive_contains(item, lst):
if not isinstance(lst, collections.Iterable):
return item == lst
for val in lst:
if item == val:
return True
elif isinstance(val, collections.Iterable):
if recursive_contains(item, val):
return True
return False
of course if you only have 2 levels (all elements of lst are lists of int), you could simply say:
if ele in sum(lst, []):
...
which uses sum to flatten the list first.
The other answers well define the mistake in your code.
Just to reiterate that you were assuming each element in the list as a nested list and subscripting it like - elem[place].
You can't subscript a primitive type such as integer and hence the error.
Refer the below code to handle nesting.
Note - You Don't require the 3rd parameter of place, more appropriately you wouldn't the place if you are searching.*
def fetch(data, l):
for element in l:
if type(element) == list:
if fetch(data, element):
return True
else:
if element == data:
return True
return False
On further thought you are looking for an element that should be only at "place" index of any of the nested lists.
Refer to the snippet below for that-
def fetch(data, l,place):
if data == l[place]:
return True
else:
for element in l:
if type(element) == list and fetch(data,element,place):
return True
return False
Note- Only call fetch again if the element is a list.
a = [[1, 2], [3, 4]]
def inlist(e, l, p):
for lists in range(len(l)):
print("array:", l[lists])
print("Looking for", e)
print("In position", p)
print(l[lists][p])
if l[lists][p] == e:
print(True, ": The element ", e, " is in the list n.", lists, " at the place ", p)
return True
inlist(2, a, 1)
Output
array: [1, 2]
Looking for 2
In position 1
2
True : The element 2 is in the list n. 0 at the place 1
For example
def find_all_occurrences(a,b):
'''
>>>find_all_occurrences('wswwswwwswwwws', ['ws', 'wws'])
[[0,3,7,12], [2,6,11]]
'''
How can I return a list of lists that have all the occurrences without import any modules.
You can use regular expressions
import re
def all_occurrences(a, b):
return [[occur.start() for occur in re.finditer(word, a)] for word in b]
Without imports it gets a little messy, but definitely still doable
def all_occurrences(a, b):
result = []
for word in b:
word_res = []
index = a.find(word)
while index != -1:
word_res.append(index)
index = a.find(word, index+1)
result.append(word_res)
return result
You can find all the occurrences by using the last found position as the start of the next search:
str.find(...)
S.find(sub [,start [,end]]) -> int
Return the lowest index in S where substring sub is found,
such that sub is contained within S[start:end]. Optional
arguments start and end are interpreted as in slice notation.
Return -1 on failure.
A loop that calls haystack.find(needle, last_pos + 1) repeatedly until it returns -1 should work.
you can also have simple list comprehensions to help with problems like these
[[i for i in range(len(a)-len(strng)+1) if strng == a[i:i+len(strng)]] for strng in b]
where
>>> a
'wswwswwwswwwws'
>>> b
['ws', 'wws']
Solution with a recursive procedure. I used a nested/inner function to maintain the OP's function signature:
def find_all_occurrences(a,b):
'''
>>>find_all_occurrences('wswwswwwswwwws', ['ws', 'wws'])
[[0,3,7,12], [2,6,11]]
'''
def r(a, b, count = 0, result = None):
if not a:
return result
if result is None:
# one sublist for each item in b
result = [[] for _ in b]
for i, thing in enumerate(b):
if a.startswith(thing):
result[i].append(count)
return r(a[1:], b, count = count + 1, result = result)
return r(a, b)
I have a function that, when inputting a list and a specific string in that list, removes any duplicates of that specific string from the list. (find_start and find_end are separate functions that determine the first and last position of a certain string)
def remove_duplicates(sorted_list, item):
i = 0
real_list = []
for x in range(len(sorted_list)-1):
if(sorted_list[i] == item):
a = find_start(sorted_list, item)
b = find_end(sorted_list, item)
real_list = real_list + [item]
i = i+(b-a)
else:
real_list = real_list + [sorted_list[i]]
i+=1
return real_list
So for example, remove_duplicates(['a','a','b','b','c','c'], 'a') would return ['a','b','b','c','c']
I'm trying to define another function that uses this function in it for each iteration, like so
def remove_all_duplicates(sorted_list):
i = 0
list_tru = []
for x in range(len(sorted_list)):
list_tru = remove_duplicates(sorted_list, sorted_list[i])
i+=1
return list_tru
but if I input remove_all(['a','a','b','b','c','c']), it outputs ['a','a','b','b','c']. What am I doing wrong?
def remove_all_duplicates(L):
# NOTE: this modifies L IN-PLACE. Tread carefully
i = 1
while i<len(L):
if L[i] == L[i-1]:
del(L[i])
continue
i += 1
Usage:
In [88]: L = ['a','a','b','b','c','c']
In [89]: remove_all_duplicates(L)
In [90]: L
Out[90]: ['a', 'b', 'c']
With every iteration, you just keep going back to the original sorted_list. I would recommend copying it and then operating on that copy:
def remove_all_duplicates(sorted_list):
list_tru = sorted_list[:] # copy it
for x in set(sorted_list): # just use a set
list_tru = remove_duplicates(list_tru, x) # remove this character from your list
return list_tru
I've also turned the sorted list into a set so that you don't try to remove duplicates of the same letter multiple times, and removed the unnecessary i counter.
Of course, if all you really want to do is remove the duplicates from a sorted list of strings and you're not attached to the algorithm you're developing, that's particularly simple:
new_list = sorted(set(old_list))
def remove_duplicates(sorted_list):
for item in sorted_list:
hits = sorted_list.count(item)
while hits > 1:
sorted_list.remove(item)
hits = sorted_list.count(item)
return sorted_list
print(remove_duplicates(["a","a", "b", "b"]))
this is the simplest method I could come up with on the spot uses .count to tell if there are duplicates returns ["a", "b"]
You can use this too:
A = ['a','a','b','c','c'] #example of input list with duplicates
value = remove_duplicates(A) #pass the list to the function
print value #prints ['a','b','c']
def remove_duplicates(A):
B = [] #empty list
for item in A:
if item in B:
pass
else:
B.append(item) #Append the list
return B
Hope that this helps. Have a nice day.
I need to write a function that will print biggest odd number from three input arguments.
Here is my code.
def oddn(x,y,z):
odd_number_keeper = []
for item in x,y,z:
global odd_number_keeper
if item % 2==1:
odd_number_keeper = [item]
return max(odd_number_keeper)
else:
print 'No odd number is found'
My codes seem is not working. Any ideas how i can modify this code?
A few changes would be needed:
def oddn(x,y,z):
odd_number_keeper = []
for item in [x,y,z]:
if item % 2==1:
odd_number_keeper.append(item)
if not odd_number_keeper:
print 'No odd number is found'
return
return max(odd_number_keeper)
Iterate over the values x, y and z and add the odd numbers to odd_number_keeper. If there are any numbers then you return the max() of the elements in this list of odd numbers. If there are no odd numbers then you print the message and return (without a result, as there is no number to return).
You have to first filter all odd-numbers and then call max:
def oddn(x,y,z):
odd_numbers = [item for item in (x,y,z) if item%2==1]
return max(odd_numbers)
or in short:
def oddn(*numbers):
return max(x for x in numbers if x % 2 == 1)
also it is not good practice, if you want to print some message on error:
def oddn(*numbers):
try:
return max(x for x in numbers if x % 2 == 1)
except ValueError:
print 'No odd number is found'
return None
You are not finding the biggest odd number from the list, instead, you are finding the first odd number and returning that. The issue is in the lines -
odd_number_keeper = [item]
return max(odd_number_keeper)
you first need to be appending item to the list, insteading of making odd_number_keeper the list with only that item.
Secondly, the return statement should be at the end of the function, not inside the for loop.
You need a code something like -
def oddn(x,y,z):
odd_number_keeper = []
for item in x,y,z:
if item % 2==1:
odd_number_keeper.append(item)
return max(odd_number_keeper)
You are resetting odd_number_keeper each time. You probably meant
odd_number_keeper += [item]
Also the return and print should be at the end of (outside) the for loop.
(please fix indentation to be clearer on your intent).
Solving it using filter. Doing it in pythonic way.
def oddn(a, b, c):
final = []
final.append(a)
final.append(b)
final.append(c)
result = filter(lambda x: x % 2 != 0, final)
return max(result)