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']
Related
e.g. find substring containing 'a', 'b', 'c' in a string 'abca', answer should be 'abc', 'abca', 'bca'
Below code is what I did, but is there better, pythonic way than doing 2 for loops?
Another e.g. for 'abcabc' count should be 10
def test(x):
counter = 0
for i in range(0, len(x)):
for j in range(i, len(x)+1):
if len((x[i:j]))>2:
print(x[i:j])
counter +=1
print(counter)
test('abca')
You can condense it down with list comprehension:
s = 'abcabc'
substrings = [s[b:e] for b in range(len(s)-2) for e in range(b+3, len(s)+1)]
substrings, len(substrings)
# (['abc', 'abca', 'abcab', 'abcabc', 'bca', 'bcab', 'bcabc', 'cab', 'cabc', 'abc'], 10)
You can use combinations from itertools:
from itertools import combinations
string = "abca"
result = [string[x:y] for x, y in combinations(range(len(string) + 1), r = 2)]
result = [item for item in result if 'a' in item and 'b' in item and 'c' in item]
This is the question of the exercise: write a function that checks if a list is sorted in ascending order.
def ascending(lst):
for k in range(0,len(lst)):
if lst[k] < lst[k+1]:
print('Ok')
else:
print('NOk, the number ' + str(lst[k]) + ' is greater than his next ' + str(lst[k+1]))
return 'Bye!'
lst = [1,3,2,4,5]
print(ascending(lst))
I expect the output: Ok, Ok, NOk the number 3 is greather than his next 2, Ok ... and I get it but, at the very end of the problem, the error message is obviously "IndexError: list index out of range". I understood that the problem is at the end of the if statement because for k = 4, k+1 = 5 (out of range) but I don't know how to solve it.
Your problem is here:
for k in range(0,len(lst)):
if lst[k] < lst[k+1]:
When k=4 ( which is len(list) ), then k+1 is out of range. Make your loop statement
for k in range(0,len(lst) - 1):
A different approach:
If your task is as simple as 'Test if a list is sorted in ascending order'; then how about a simple function like:
def issorted(lst):
return lst == sorted(lst)
print('Is sorted: ', issorted([5, 4, 1, 2]))
print('Is sorted: ', issorted([1, 2, 3, 4]))
print('Is sorted: ', issorted(['a', 'b', 'd', 'c']))
print('Is sorted: ', issorted(['w', 'x', 'y', 'z']))
Which outputs:
Is sorted: False
Is sorted: True
Is sorted: False
Is sorted: True
The easiest:
def ascending(lst):
lst == sorted(lst)
But this is log-linear and does not short-circuit. Better:
def ascending(lst):
return all(a <= b for a, b in zip(lst, lst[1:]))
or in Python >= 3.10:
from itertools import pairwise
def ascending(lst):
return all(a <= b for a, b in pairwise(lst))
I have a string and a list:
seq = '01202112'
l = [(0,1,0),(1,1,0)]
I would like a pythonic way of replacing each '2' with the value at the corresponding index in the list l such that I obtain two new strings:
list_seq = [01001110, 01101110]
By using .replace(), I could iterate through l, but I wondered is there a more pythonic way to get list_seq?
I might do something like this:
out = [''.join(c if c != '2' else str(next(f, c)) for c in seq) for f in map(iter, l)]
The basic idea is that we call iter to turn the tuples in l into iterators. At that point every time we call next on them, we get the next element we need to use instead of the '2'.
If this is too compact, the logic might be easier to read as a function:
def replace(seq, to_replace, fill):
fill = iter(fill)
for element in seq:
if element != to_replace:
yield element
else:
yield next(fill, element)
giving
In [32]: list(replace([1,2,3,2,2,3,1,2,4,2], to_replace=2, fill="apple"))
Out[32]: [1, 'a', 3, 'p', 'p', 3, 1, 'l', 4, 'e']
Thanks to #DanD in the comments for noting that I had assumed I'd always have enough characters to fill from! We'll follow his suggestion to keep the original characters if we run out, but modifying this approach to behave differently is straightforward and left as an exercise for the reader. :-)
[''.join([str(next(digit, 0)) if x is '2' else x for x in seq])
for digit in map(iter, l)]
I don't know if this solution is 'more pythonic' but:
def my_replace(s, c=None, *other):
return s if c is None else my_replace(s.replace('2', str(c), 1), *other)
seq = '01202112'
l = [(0,1,0),(1,1,0)]
list_req = [my_replace(seq, *x) for x in l]
seq = '01202112'
li = [(0,1,0),(1,1,0)]
def grunch(s, tu):
it = map(str,tu)
return ''.join(next(it) if c=='2' else c for c in s)
list_seq = [grunch(seq,tu) for tu in li]
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'])
these are my lists
i=["a","b"]
j=["abc","(3)","ab & ac", "(1,4)","xyz"]
and I want my output be like this
j=["abc","a","ab & ac","b","xyz"]
and i tried like this,
val=0
for item in j:
if item.isalpha():
pass
else:
elem=i[val]
j.replace(item, elem)
val=val+1
How to insert item from one list to other at position which does not contains alphanumeric?
Assuming that "ab & ac" is not alphanumeric (because of the & and whitespaces) and that you made a typo, this will do the trick.
def removeNonAlpha(i,j):
indexI = 0
indexJ = 0
while indexJ < len(j):
if not j[indexJ].isalnum():
j[indexJ] = i[indexI]
indexI += 1
indexJ += 1
return j
>>>i=["a","b", "c"]
>>>j=["abc","(3)","ab & ac", "(1,4)","xyz"]
>>>removeNonAlpha(i,j)
['abc', 'a', 'b', 'c', 'xyz']
This code also assumes that you have enough elements in i to make complete replacements for j.
If for some special reasons you need to allow & signs (which would imply that you would also need to allow the whitespaces) here is the alternative:
def removeNonAlpha(i,j):
indexI = 0
indexJ = 0
while indexJ < len(j):
if not j[indexJ].replace('&', '').replace(' ', '').isalnum():
j[indexJ] = i[indexI]
indexI += 1
indexJ += 1
return j
>>>i=["a","b"]
>>>j=["abc","(3)","ab & ac", "(1,4)","xyz"]
>>>removeNonAlpha(i,j)
['abc', 'a', 'ab & ac', 'b', 'xyz']
This will preserve any list element in a list j that has a letter in it
[s for s in j if any(c in string.letters for c in s)]
If you have a character or string than doesn't occur in any of the strings, you can concatenate the list into a single string using the string .join method, then use a regular expression and the re.sub function to do the replacement. After that, you can use the .split method to divide the string back into a list:
>>> import re
>>> i=["a","b"]; j=["abc","(3)","ab & ac", "(1,4)","xyz"]
>>> js = "|".join(j) # merge j into one string
>>> print js
abc|(3)|ab & ac|(1,4)|xyz
>>> print re.sub("\(.*?\)", i[0], js)
abc|a|ab & ac|a|xyz
>>> print re.sub("\(.*?\)", i[0], js, count=1)
abc|a|ab & ac|(1,4)|xyz
>>> for r in i:
js = re.sub("\(.*?\)", r, js, count=1)
>>> print js
abc|a|ab & ac|b|xyz
That for loop at the end shows you how to do it. The parenthesized fields will be filled in, one at a time, from left to right. To put it back into a list:
jnew = js.split("|")
...and you're done.
It's not clear what your definition of "alphanumeric" is. Your example uses isalpha, which "ab & ac" fails, as DSM pointed out. If isalpha is an acceptable definition of "alphanumeric", and it's OK to modify the arrays, then I propose the following:
for index, item in enumerate(j):
if not item.isalpha():
j[index] = i.pop(0) if i else None
There's probably a list comprehension version of this, but it would be messy.
Note that the above code produces the following result, given your sample inputs:
['abc', 'a', 'b', None, 'xyz']
That's because there aren't actually enough items in i to cover all the non-alphanumeric members of j, so I used None in that case.