Accumulating lists with letters - python

I'm trying to right a code that accumulates a list.
The code I've figured out so far does that but I want to make it work with letters e.g.
accumulate("a", "b", "c")
would come out to be a, ab, abc.
def accumulate(L):
theSum = 0
for i in L:
theSum = theSum + i
print(theSum)
return theSum
accumulate([1, 2, 3])

While #WillemVanOnsem has provided you with the method that would work, to shorten your code you can use itertools.accumulate from the standard library:
>>> from itertools import accumulate
>>>
>>> for step in accumulate(['a', 'b', 'c']):
print(step)
a
ab
abc
>>>

You can try this:
import string
l = string.ascii_lowercase
the_list = []
letter = ""
for i in l:
letter += i
the_list.append(letter)
Even better in a function with a generator:
def accumulation():
l = string.ascii_lowercase
letter = ""
for i in l:
letter += i
yield letter
the_letters = list(accumulation())
print(the_letters)
Output:
['a', 'ab', 'abc', 'abcd', 'abcde', 'abcdef', 'abcdefg', 'abcdefgh', 'abcdefghi', 'abcdefghij', 'abcdefghijk', ...]

If you want to let it work with strings, you have to initialize it with an empty string:
def accumulate(*args):
theSum = ''
for i in args:
theSum += i # we can here shorten it to += (kudos to #ChristianDean)
print(theSum)
return theSum
Furthermore if you want to use an arbitrary number of arguments, you should use *args (or *L).
Now of course this will no longer work with numbers. The theSum += i is here short for theSum = theSum + i (since strings are immutable). Note however that this is not always the case: for lists there is a difference for instance.
Now it prints:
>>> accumulate("a", "b", "c")
a
ab
abc
'abc'
The last 'abc' is not a result of a print(..) statement, but it is the return of the accumulate function.

Related

how to upper string characters at once?

i want to take astring and indeses on that string and to convert these characters on those indexes to upper.
this is what I've tried but it doesn't work. it shows
"list indices must be integers or slices, not list"
test = 'hello there'
l = list(test)
def capital(s, ind):
for i in s:
i = list(i)
i[ind] = i[ind].upper()
print(s)
capital(l,[1,2,5])
It doens't seem correct to iterate over each character of the string. A more correct approach would be to iterate on each index in ind and capitalize those characters.
Anyway this can be one with a one-liner using a list comprehension:
def capital(s, ind):
capitalized = [s[i].upper() if i in ind else s[i] for i in range(len(s))]
return ''.join(capitalized)
People are overcomplicating this in their answers. You shouldn't need to iterate over the string, if you already have a defined list of indexes to capitalize. Here's what you can do, iterating only over the indexes parameter:
def capital(text, indexes):
split_text = list(text)
for i in indexes:
split_text[i] = split_text[i].upper()
return ''.join(split_text)
capitalized = capital('hello there', [1, 2, 5])
print(capitalized)
This would print hELlo there.
A shorter alternative would be using the function enumerate, since you're working with both values and indexes of a sequence (string):
def capital(text, indexes):
return ''.join(c.upper() if i in indexes else c for i,c in enumerate(text))
This would also work perfectly fine.
I think you mixed up the list you pass as a second parameter in your capital function and the list of caracters you have created.
Here is a way to properly write your function :
test = 'hello there'
def capital(s, ind):
for i in ind:
s[i] = s[i].upper()
return(s)
print(capital(list(test),[1,2,5]))
Here is the corrected way to define a function that takes in a list of characters and a list of indexes, and prints out the list with the specified indexes uppercased:
test = 'hello there'
l = list(test)
def capital(s, ind):
for i in ind:
s[i] = s[i].upper()
print(s)
capital(l,[1,2,5])
Output:
['h', 'E', 'L', 'l', 'o', ' ', 't', 'h', 'e', 'r', 'e']
Here is a simpler version that does not require a pre-conversion from a string to a list, it simply takes in a string and a list of indices:
def capital(s, ind):
s = ''.join([c.upper() if i in ind else c for i,c in enumerate(s)])
print(s)
capital('hello world',[1,2,5])
Output:
hELlo world
see fixes in line. you meant to do this this is the right way to to do it.
in your code i[ind] = i[ind].upper(). ind is a list! this is an error. see my code below:
test = 'hello there'
l = list(test)
def capital(s, ind):
for i in range(len(s)): #i is one letter - charachter
if i in ind:
s[i] = s[i].upper() #it expects an integer! you have passed a list
print(s)
capital(l, [1,2,5])
Effictive approach
test = 'hello there'
l = list(test)
def capital(s, ind):
for i in ind: #i is one letter - charachter
s[i] = s[i].upper() #it expects an integer! you have passed a list
print(s)
capital(l, [1,2,5])

I want to remove elements from the list from the string when the elements of the list are in the string

Suppose
a = ['ab','bcd','efg','h']
b = ['wiab','wbcdz','rh','ksw','erer']
I want to remove any of the characters listed in a from list b.
result should be `['wi','wz','r','ksh','erer']
This is the code I tried :
result = []
for i in b:
if not any(word in i for word in a):
result.append(word)
But this code returns
result = ['ksw','erer']
please help me
def function(a,b):
result = []
for i in a:
for word in b:
if i in word:
result.append(word.replace(i,''))
return result
The any function in your code is unnecessary. You need to loop through both lists, then check if your substring is in the string of the other list, call the replace method on your word containing the substring, and then add it to your list of results
Other solutions give you what you want so here is one for a bit of fun. You can use functools.reduce with a custom function.
from functools import reduce
a = ['ab','bcd','efg','h']
b = ['wiab','wbcdz','rh','ksw','erer']
def remove(x, y):
return x.replace(y, '')
out = [reduce(remove, a, i) for i in b]
giving
['wi', 'wz', 'r', 'ksw', 'erer']
Edit:
Probably the least clear way you could write this would be as a one-liner with a lambda :)
[reduce(lambda x, y: x.replace(y, ''), a, i) for i in b]
a = ['ab','bcd','efg','h']
b = ['wiab','wbcdz','rh','ksw','erer']
result = []
for i in b:
for word in a:
if word in i:
result.append(i.replace(word, ''))
print(result)
Output:
['wi', 'wz', 'r']

How can you sort a string backwords, by vowels and consonant?

So I have to create a program that rewrites a string backword and alternates vowels and consonants like in this example:
ex_1:
input -> 'abcdefi'
output -> 'ifedacb'
ex_2:
input -> 'vblsdeloai'
output ->'iladoselbv'
What I did so far:
word = input('the word is: ')
b = word[::-1]
list_vowels = []
list_consonants = []
final_list = []
string = ''
vowels = ['a', 'e','i','o','u']
for i in str(b):
if i in vowels:
list_vowels.append(i)
elif i not in vowels:
list_consonants.append(i)
part where I'm stuck
for j in list_vowels :
final_list.append(j)
for b in list_consonants :
final_list.append(b)
converts my final list into a string
for q in e
string = string + e
print (string)
so I convert the string backwords than I use a for to iterate over every char and compare it to the vowel list. If it is in the vowel list then append to a new list list_vowels if not append it to a new list list_consonants.
Now I'm stuck at the part where I have to create a list that is created by the two list list_vowels and list_consonats. I don't now how can I make the two for work simultaniously. The zip functions make the list a tuple and I don't think I can use that. I'm prety new and any help will be awsome. If you think I can aproach this problem differently feel free to tell me I am new to programing and I don't realy now how.
You need itertools.zip_longest to zip through two lists taking an empty string as fillvalue:
''.join(map(lambda x: x[0] + x[1], zip_longest(list_vowels, list_consonants, fillvalue='')))
Code:
from itertools import zip_longest
word = input('the word is: ')
b = word[::-1]
list_vowels = []
list_consonants = []
final_list = []
string = ''
vowels = ['a', 'e','i','o','u']
for i in b:
if i in vowels:
list_vowels.append(i)
elif i not in vowels:
list_consonants.append(i)
print(''.join(map(lambda x: x[0] + x[1], zip_longest(list_vowels, list_consonants, fillvalue=''))))
The line you're missing is turning your two list of 1) vowels and 2) consonants into a zipped string. You can do this with itertools.zip_longest().
This is the line you will need:
from itertools import zip_longest
''.join(''.join(x) for x in zip_longest(list_vowels, list_consonants, fillvalue=''))
In[1]: 'vblsdeloai'
Out[1]: 'iladoselbv'
from itertools import zip_longest
def split(s):
vowels = ['a', 'e', 'i', 'o', 'u']
return list(filter(lambda c: c in vowels, s)), \
list(filter(lambda c: c not in vowels, s))
def reverse_interleave(s):
vowels, consonants = list(map(reversed, split(s)))
return ''.join(
map(lambda x: ''.join(x),
zip_longest(vowels, consonants, fillvalue='')))
print(reverse_interleave('abcdefi'))
print(reverse_interleave('vblsdeloai'))
Split the characters into vowels and non-vowels.
Reverse them.
Interleave them using zip_longest() in this case.

There is something wrong with my Python code involve the replace function

I was creating a function about replacing multiple part of a string with multiple number but for some reason, the output is not what i expected.
from pyprimes import isprime
def prime_replace(x, l = []):
lst = []
string = str(x)
for n in range(10):
for i in l:
string = string.replace(string[i], str(n))
lst.append(int(string))
return lst
print prime_replace(x = 56243, l = [2, 3])
The output of this function is a list [56003, 56113, 56223, 56333, 56444, 56555, 66666, 77777, 88888, 99999] but what i wanted is [56003, 56113, 56223, 56333, 56443, 56553, 56663, 56773, 56883, 56993] Can someone help me with this and tell me what went wrong, thank you.
You're modifying the original string, and replace is replacing "all occurrences"
Here's part of a print out for how it's generating the output you see:
...
string is now 56333
replacing 3 with 3
string is now 56333
replacing 3 with 4
string is now 56444
...
You can see that we successfully got 56333 like you wanted, but then you wanted to replace str[2] (actual value: 3) with str(n) (actual value: 4), which replaced all occurrences of 3
One workaround for this specific scenario is to make a copy of your string:
def prime_replace(x, l = []):
lst = []
string = str(x)
for n in range(10):
newstr = string
for i in l:
newstr = newstr.replace(string[i], str(n))
lst.append(int(newstr))
return lst
print prime_replace(x = 56243, l = [2, 3])
Output:
[56003, 56113, 56223, 56333, 56443, 56553, 56663, 56773, 56883, 56993]
Demo (not recommended)
However, replace may not be the best choice since it will replace all occurrences of the "oldstring" with the "newstring". It looks like what you're really trying to do is to change string at indices in l to be the next value in range(10), we can do this through indexing and appending:
def prime_replace(x, l = []):
lst = []
string = str(x)
for n in range(10):
newstr = string
for i in l:
newstr = newstr[0:i]+str(n)+newstr[i+1:];
lst.append(int(newstr))
return lst
Demo (better)
string.replace(a,b) replaces all instances of a with b. so, '56243'.replace(3,0) evaluates to '56240'. You are trying to replace the values at the indicies in l, so you should replace
string = string.replace(string[i], str(n))
with
string = string[:i] + str(n) + string[i+1:]
The other answer fails on cases where the value at an index to be replaced is repeated elsewhere in the number, i.e. prime_replace(562432,[2,3])
I have also found another solution for it by turning the string into list
from pyprimes import isprime
def prime_replace(x, l):
lst = []
string_lst = list(str(x))
for n in range(10):
for i in l:
string_lst[i] = str(n)
lst.append(int("".join(string_lst)))
return lst
print prime_replace(56243, [2, 3])
Output
[56003, 56113, 56223, 56333, 56443, 56553, 56663, 56773, 56883, 56993]
But thank you very much for your solution.
You really want a mutable data-structure here to simplify your logic. You can get what is essentially a mutable string by using a bytearray. So here is an alternative approach:
In [11]: def prime_replace(x, l=None):
...: if l is None:
...: l = [] # careful with mutable default arguments
...: lst = []
...: string = bytearray(str(x), encoding='ascii')
...: for n in b'0123456789':
...: for i in l:
...: string[i] = n
...: lst.append(int(string))
...: return lst
...:
In [12]: prime_replace(x = 56243, l = [2, 3])
Out[12]: [56003, 56113, 56223, 56333, 56443, 56553, 56663, 56773, 56883, 56993]
Also, be careful with mutable default arguments.
I use a bytearray because I think it simplifies things more. A list also works. But note with bytearray and by iterating directly over the ascii b'012345679' it simplifies everything by a lot, and you don't have to keep converting things back-and-forth between str and int

Splitting a list by first character of each element

I have a Python list mylist whose elements are a sublist containing a string of a letter and number. I was wondering how I could split mylist by the character at the start of the string without using code with individual statements/cases for each character.
Say I want to split mylist into lists a, b, c:
mylist = [['a1'],['a2'],['c1'],['b1']]
a = [['a1'],['a2']]
b = [['b1']]
c = [['c1']]
It is important that I keep them as a list-of-lists (even though it's only a single element in each sublist).
This will work:
import itertools as it
mylist = [['a1'],['a2'],['c1'],['b1']]
keyfunc = lambda x: x[0][0]
mylist = sorted(mylist, key=keyfunc)
a, b, c = [list(g) for k, g in it.groupby(mylist, keyfunc)]
The line where sorted() is used is necessary only if the elements in mylist are not already sorted by the character at the start of the string.
EDIT :
As pointed out in the comments, a more general solution (one that does not restrict the number of variables to just three) would be using dictionary comprehensions (available in Python 2.7+) like this:
result_dict = {k: list(g) for k, g in it.groupby(mylist, keyfunc)}
Now the answer is keyed in the dictionary by the first character:
result_dict['a']
> [['a1'],['a2']]
result_dict['b']
> [['b1']]
result_dict['c']
> [['c1']]
Using a dictionary could work too
mylist = [['a1'],['a2'],['c1'],['b1']]
from collections import defaultdict
dicto = defaultdict(list)
for ele in mylist:
dicto[ele[0][0]].append(ele)
Result:
>>> dicto
defaultdict(<type 'list'>, {'a': [['a1'], ['a2']], 'c': [['c1']], 'b': [['b1']]})
It does not give the exact result you were asking for; however, it is quite easy to access a list of lists associated with each letter
>>> dicto['a']
[['a1'], ['a2']]
You can also get these sublists by using a simple function:
def get_items(mylist, letter):
return [item for item in mylist if item[0][0] == letter]
The expression item[0][0] simply means to get the first letter of the first element of the current item. You can then call the function for each letter:
a = get_items(mylist, 'a')
b = get_items(mylist, 'b')
c = get_items(mylist, 'c')

Categories