These three functions are apart of my study guide and would greatly appreciate some assistance.
In each case, the function returns a value (so use the return statement): it does not print the value (no print statement) or mutate (change the value of) any of its arguments.
1) The repl function takes three arguments:
◦old is any value;
◦new is any value;
◦xs is a list.
Example:
>>> repl('zebra', 'donkey', ['mule', 'horse', 'zebra', 'sheep', 'zebra'])
['mule', 'horse', 'donkey', 'sheep', 'donkey']
It returns a new list formed by replacing every occurrence of old in xs with new.
It must not mutate the list xs; i.e., after return from the function, the actual argument given for xs must be what it was before.
>>> friends = ['jules', 'james', 'janet', 'jerry']
>>> repl('james', 'henry', friends)
['jules', 'henry', 'janet', 'jerry']
>>> friends
['jules', 'james', 'janet', 'jerry']
2) The search function looks for a value in a list. It takes two arguments:
◦y is the value being searched for.
◦xs is the list being searched in.
It returns the index of the first occurrence of y in xs, if it occurs; −1 otherwise.
Examples:
>>> words = ['four', 'very', 'black', 'sheep']
>>> search('four', words)
0
>>> search('sheep', words)
3
>>> search('horse', words)
-1
3) The doubles function is given a list of numbers and returns a new list containing the doubles of every number in the given list.
Example:
>>> doubles([1, 3, 7, 10])
[2, 6, 14, 20]
It must not mutate the given list:
>>> salaries = [5000, 7500, 15000]
>>> doubles(salaries)
[10000, 15000, 30000]
>>> salaries
[5000, 7500, 15000]
This is to be done without using any list methods except append. (In particular, you may not use the index or count for the search function.)
Although you can use the list len function, and the list operations +, *, indexing, slicing, and == for comparing lists or elements. You will need to use some of these but not all.
Any help is greatly appreciated like I mentioned in the introduction.
So far all I have is.
def repl (find, replacement, s):
newString = ''
for c in s:
if c != find:
newString = newString + c
else:
newString = newString + replacement
return newString
def search(y, xs):
n = len(xs)
for i in range(n):
if xs[i] == y:
return i
return -1
and....
def search(key,my_list):
if key in my_list:
return my_list.index(key)
else:
return
I'm not sure what needs to be returned after the else statement.
def relp(old,new,my_list):
final = []
for x in my_list:
if x is old:
final.append(new)
else:
final.append(x)
return final
def search(key,my_list):
if key in my_list:
return my_list.index(key)
else:
return -1
def doubles(my_list):
return[x*x for x in my_list]
I suspect this lesson is about list comprehensions
doubles = lambda my_list: [x*2 for x in my_list]
repl = lambda old_t,new_t,my_list: [x if x != old_t else new_t for x in my_list]
print repl("cow","mouse",["cow","rat","monkey","elephant","cow"])
print doubles([1,2,3,4,'d'])
Related
I'm wondering if there is a way to check if any combination of more than two items from a list exists in another list?
list_1 = ['apple','soap','diet coke','banana','sweets','mash','fruit','veggies']
for string in lists:
strings = string.split()
print(strings)
SAMPLE OUTPUT for strings:
['today', 'i','bought','banana','but','forgot','soap', 'and','veggies']# this line should identify 'banana', 'soap' and 'veggies'
['maybe', 'there','are','more','sweets','left','later'] # this line should be ignored, because not more than 2 items of the list are in it
['food', 'shopping','is','boring','and','i','hate','mash','with','veggies']# this line should identify 'mash' and 'veggies'
I know that by using this piece of code, I can at least check if any of the elements appear in strings:
combinations = any(i in list_1 for i in strings)
You can use set intersection and check the resulting size:
s1 = set(list_1)
if len(s1.intersection(strings)) >= 2:
# do stuff
This will, however, not trigger if the same item occurs twice in strings which may or may not be what you desire. In that case, you could do something like:
if sum(s in s1 for s in strings) >= 2:
# do stuff
I was late apparently. This is basically schwobaseggl's solution wrapped as a function
mylist = ['apple','soap','diet coke','banana','sweets','mash','fruit','veggies']
mytest = ['today', 'i','bought','banana','but','forgot','soap', 'and','veggies']
def common_elements(mylist, mytest):
common_elements = list(set(mylist).intersection(mytest))
if len(common_elements)>2:
return common_elements
else:
pass
This should work:
string = ['today', 'i','bought','banana','but','forgot','soap', 'and','veggies']
list_1 = ['apple','soap','diet coke','banana','sweets','mash','fruit','veggies']
n = 0
inv = []
for i in string:
if i in list_1:
inv.append(i)
n += 1
if n >= 2:
print(inv)
or you can put it into a define and make yourself a function:
def check(string,list_1):
inv = []
for i in string:
if i in list_1:
inv.append(i)
if len(inv) >= 2:
return inv
else: return []
string = ['today', 'i','bought','banana','but','forgot','soap', 'and','veggies']
list_1 = ['apple','soap','diet coke','banana','sweets','mash','fruit','veggies']
print(check(string,list_1))
You can try this "hard-coded" way too
list1=['apple','soap','diet coke','banana','sweets','mash','fruit','veggies']
list2 = ['today', 'i','bought','banana','but','forgot','soap', 'and','veggies']
def check(list_1,list_2) :
common = list()
for i in list_1 :
if i in list_2 :
common.append(i)
if len(common) >=2 :
return common
else :
return "Less than two items are common"
try = check(list_1,list_2)
If I am not wrong, you want to find out that 2 lists have more than 2 same element?
def intersection(list_one, list_two):
intersection = set(list_one) & set(list_two)
if len(list(intersection)) > 1:
print(list(intersection))
return False
a = [1, 2, 3, 4]
b = [1, 8, 9, 10]
c = [1, 2, 5, 6]
intersection(a, b) # return False
intersection(a, c) # return [1, 2]
I have an tuple containing 100 string values (say). Now, I want to check if two string elements there in the tuple are same?
I tried to do something like this with nested loops:
def hasDuplicates(arr: tuple):
ctr = 0
# arr looks something like this & len(arr) == 100
# arr = ('abc', 'bcd', 'sdf', 'abc', 'pqr', ...)
for m in arr:
for n in arr:
if n == m:
ctr += 1
# while looping, len(arr) times every element
# will be compared with itself
if ctr > len(arr):
return True
return False
...which worked but I think there is a better work around for this. Can anyone provide a better solution to this? :)
If I understand correctly, you can just convert your tuple to a set and check whether it has the same length as the original tuple.
def has_duplicates(iterable):
l = list(iterable) # in case iterable is an iterator
return len(set(l)) != len(l)
Demo:
>>> tup = ('abc', 'bcd', 'sdf', 'abc', 'pqr')
>>> has_duplicates(tup)
>>> True
>>> has_duplicates(range(100))
>>> False
Won't work for infinite iterators :)
~edit~
A more general version that does not have to build a potentially long list and set upfront:
def has_duplicates(iterable):
seen = set()
for x in iterable:
if x in seen:
return True
seen.add(x)
return False
Of course, both versions require the elements of your iterable to be hashable.
You can also check this using any keyword and count method from list object:
arr = ('abc', 'bcd', 'sdf', 'abc', 'pqr')
def sameStrings(arr):
return any(arr.count(elem)>1 for elem in list(arr))
print(sameStrings(arr))
Output:
True
Edit
Updating answer with proposed solution by #timgeb using Counter from collections module:
from collections import Counter
arr = ('abc', 'bcd', 'sdf', 'abc', 'pqr')
def sameStrings(arr):
myCounter = Counter(list(arr))
return max(myCounter.values())>1
print(sameStrings(arr))
Output:
True
has_duplicates = len(set(some_tuple)) == 1
I tried this piece of code, but it only performs the function on the first string in the list:
returns the first and last 2 characters of the given list of strings
def both_ends(list):
finalList = []
for s in list:
if s > 2:
return s[0] + s[1] + s[-2] + s[-1]
else:
return s
finalList.append(s)
return finalList
list = ('apple', 'pizza', 'x', 'joke')
print both_ends(string)
How would I make this function run through all of the strings in the list?
Yes, that is because you are returning the result directly , so it returns after you go through the first string itself. Instead you should put the result in the finalList you create and return the result at the end.
And some other things -
As said in the other answer, you want to check the length of the string.
The length of the string should be greater than 4 , otherwise, you would end up adding some characters multiple times.
Do not use names like list for variables, it ends up shadowing the builtin functions and so you would not be able to use list() to create list after that.
Last issue is you should call you function with your list, not string .
Example -
def both_ends(list):
finalList = []
for s in list:
if len(s) > 4:
finalList.append(s[:2] + s[-2:])
else:
finalList.append(s)
return finalList
An easier way to do this -
def both_ends(s):
return s[:2] + s[-2:] if len(s) > 4 else s
lst = ('apple', 'pizza', 'x', 'joke')
print map(both_ends, lst) #You would need `list(map(...))` for Python 3.x
Demo -
>>> def both_ends(s):
... return s[:2] + s[-2:] if len(s) > 4 else s
...
>>> lst = ('apple', 'pizza', 'x', 'joke')
>>> print map(both_ends, lst)
['aple', 'piza', 'x', 'joke']
Or even list comprehension , though to me that makes it a bit less readable -
[s[:2] + s[-2:] if len(s) > 4 else s for s in lst]
Demo -
>>> lst = ('apple', 'pizza', 'x', 'joke')
>>> [s[:2] + s[-2:] if len(s) > 4 else s for s in lst]
['aple', 'piza', 'x', 'joke']
You want to check the length of the string, not the string itself. Hence, doing s > 2 doesn't do what you want it to do:
def both_ends(lst):
finalList = []
for s in lst:
if len(s) > 2:
finalList.append(s[0] + s[1] + s[-2] + s[-1])
else:
finalList.append(s)
return finalList
lst = ['apple', 'pizza', 'x', 'joke']
print both_ends(lst)
Few other things:
Don't name variables list. It will override the built-in type.
You have a tuple (..., ...). A list is with square brackets.
You have print both_ends(string), and not putting in your list.
And finally, you can probably shorten up your code:
print [s[:2] + s[-2:] if len(s) > 2 else s for s in lst]
There are some issues that caught my eye.
You are returning immediately after the first iteration, so getting only the first element.
I think you want to compare if the length is greater than 4, so do len(s)>4
Don't use a datatype name as a variable name. Use used list, don't use that.
Don't return immediately, rather append to the list.
def both_ends(lst):
finalList = []
for s in lst:
if len(s) > 4:
finalList.append( s[0] + s[1] + s[-2] + s[-1])
else:
finalList.append(s)
return finalList
lst = ['apple', 'pizza', 'x', 'joke']
print both_ends(lst)
Output:
['aple', 'piza', 'x', 'joke']
I want to write a Python function which checks if one string is a prefix string of another; not an arbitrary sub string of another; must be prefix. If it is, return True. For instance,
list = ['abc', 'abcd', 'xyx', 'mno']
Return True because 'abc' is a prefix of 'abcd'.
list = ['abc', 'xyzabc', 'mno']
Return False
I tried the startwith() and list comprehension, but it didn't quite work.
Appreciate for any help or pointers.
Let us first sort the given lst w.r.t length of the string, due to the known fact that sub strings always have length less than or equal to the original string, so after sorting we have strings with smaller length at the start of the list, and then we iterate over the sorted list comparing the current element with all the elements next to it, This small optimization would reduce the complexity of the problem as now we don't have to comapre each element with every other element.
lst1 = ['abc', 'abcd', 'xyx', 'mno']
lst2 = ['abc', 'xyzabc', 'mno']
lst3 = ["abc", "abc"]
def check_list(lst):
lst = list(set(lst)) #if you want to avoid redundant strings.
lst.sort(key = lambda x:len(x))
n = len(lst)
for i in xrange(n):
for j in xrange(i+1, n):
if lst[j].startswith(lst[i]):
return True
return False
print check_list(lst1)
print check_list(lst2)
print check_list(lst3)
>>> True
>>> False
>>> False #incase you use lst = list(set(lst))
Using itertools
import itertools
list1 = ["abc", "xyz", "abc123"]
products = itertools.product(list1, list1)
is_substringy = any(x.startswith(y) for x, y in products if x != y)
This isn't very optimised, but depending on the amount of data you've got to deal with, the code is fairly elegant (and short); that might trump speed in your use case.
This assumes that you don't have pure repeats in the list however (but you don't have that in your example).
import itertools
mlist = ['abc', 'abcd', 'xyx', 'mno']
#combination of list elements, 2-by-2. without repetition
In [638]: for i,j in itertools.combinations(mlist,2):
print (i,j)
.....:
('abc', 'abcd')
('abc', 'xyx')
('abc', 'mno')
('abcd', 'xyx')
('abcd', 'mno')
('xyx', 'mno')
#r holds the final result. if there is any pair where one is a prefixed of another
r=False
In [639]: for i,j in itertools.combinations(mlist,2):
r = r or i.startswith(j) # if i is the prefix of j. logical or
r = r or j.startswith(i) # if j is the prefix of i
.....:
In [640]: r
Out[640]: True
I have a list which consists irregular words and float numbers, I'd like to delete all these float numbers from the list, but first I need to find a way to detect them. I know str.isdigit() can discriminate numbers, but it can't work for float numbers. How to do it?
My code is like this:
my_list = ['fun','3.25','4.222','cool','82.356','go','foo','255.224']
for i in my_list:
if i.isdigit() == True:
my_list.pop(i)
# Can't work, i.isdigit returns False
Use exception handling and a list comprehension. Don't modify the list while iterating over it.
>>> def is_float(x):
... try:
... float(x)
... return True
... except ValueError:
... return False
>>> lis = ['fun','3.25','4.222','cool','82.356','go','foo','255.224']
>>> [x for x in lis if not is_float(x)]
['fun', 'cool', 'go', 'foo']
To modify the same list object use slice assignment:
>>> lis[:] = [x for x in lis if not is_float(x)]
>>> lis
['fun', 'cool', 'go', 'foo']
Easy way:
new_list = []
for item in my_list:
try:
float(item)
except ValueError:
new_list.append(item)
Using regular expressions:
import re
expr = re.compile(r'\d+(?:\.\d*)')
new_list = [item for item in my_list if not expr.match(item)]
A point about using list.pop():
When you use list.pop() to alter an existing list, you are shortening the length of the list, which means altering the indices of the list. This will lead to unexpected results if you are simultaneously iterating over the list. Also, pop() takes the index as an argument, not the element. You are iterating over the element in my_list. It is better to create a new list as I have done above.
A dead simple list comprehension, adding only slightly to isdigit:
my_list = [s for s in my_list if not all(c.isdigit() or c == "." for c in s)]
This will remove string representations of both int and float values (i.e. any string s where all characters c are numbers or a full stop).
As I understand OP the function should only remove floats. If integers should stay - consider this solution:
def is_float(x):
try:
return int(float(x)) < float(x)
except ValueError:
return False
my_list = ['fun', '3.25', 'cool', '82.356', 'go', 'foo', '255.224']
list_int = ['fun', '3.25', 'cool', '82.356', 'go', 'foo', '255.224', '42']
print [item for item in my_list if not is_float(item)]
print [item for item in list_int if not is_float(item)]
Output
['fun', 'cool', 'go', 'foo']
['fun', 'cool', 'go', 'foo', '42']
Regular expressions would do the trick - this code searches each string for the format of a float (including floats starting with or ending with a decimal point), and if the string is not a float, adds it to the new list.
import re
my_list = ['fun','3.25','4.222','cool','82.356','go','foo','255.224']
new_list = []
for pos, st in enumerate(my_list):
if not re.search('[0-9]*?[.][0-9]*', st):
new_list.append(st)
print new_list
Creating a new list avoids working on the same list you are iterating on.
Ewans answer is cleaner and quicker, I think.