I'm trying to create my own function that converts a list of characters into a string. I'm not allowed to use 'join'. I need to use a loop to do this. I think I have the basis of it right, but I'm not really sure how to implement it into the function properly. I'm new to programming.
Here's the code I'm using:
def to_string(my_list):
# This line will eventually be removed - used for development purposes only.
print("In function to_string()")
# Display letters in a single line
for i in range(len(my_list)):
print(my_list[i], end='')
# Separate current letter from the next letter
if i<(len(my_list))-1:
print(", ", end='')
# Returns the result
return ('List is:', my_list)
That returns the result I want (if the list is ['a', 'b', 'c'] it returns a, b, c). But there's a 'test file' we're meant to use to run the function which contains this code:
print("\nto_string Test")
string = list_function.to_string(str_list1)
print(string)
print(list_function.to_string(empty))
And it gives this result:
to_string Test
In function to_string()
r, i, n, g, i, n, g('List is:', ['r', 'i', 'n', 'g', 'i', 'n', 'g'])
In function to_string()
('List is:', [])
Which seems to indicate that I messed up entirely, something to do with the 'print' function I think. Can anyone please tell me where I'm going wrong?
Your function prints your string to stdout, then returns the list itself unchanged.
Build a string and return that instead of printing:
def to_string(my_list):
result = ''
last = len(my_list) - 1
for pos, elem in enumerate(my_list):
result += str(elem)
if pos != last:
result += ', '
return result
This loops over all elements, keeping a position counter with the enumerate() function; this way it's easy to detect if we are adding the last element to the result.
You could also use reduce function:
aList=['w','o','r','d']
aString=reduce(lambda x,y:x+y,aList)
If you want to emulate the .join() method of strings than you may want to add a delimiter option to your function.
def to_string(my_list, delimiter):
string = str(my_list.pop(0))
while my_list:
string += delimiter + str(my_list.pop(0))
return string
.pop(n) will delete the nth element from the list and return it.
If you want to return the original list as well:
def to_string(my_list, delimiter):
string = ''
if my_list:
string = my_list[0]
for elem in my_list[1:]:
string += delimiter + str(elem)
return my_list, string
The syntax my_list[n] will get the nth element from the list. Note that the elements are numbered from 0, not from 1. The syntax my_list[n:] will return the elements of the list starting from n. Example:
>>> my_list = ['this', 'is', 'a', 'list']
>>> my_list[1:]
['is', 'a', 'list']
Loop over the list elements and add them to your string. (Just a simpler version of the proposed solutions)
def to_string(my_list):
result_string = ''
for element in my_list:
result_string += element
return result_string
To test:
a_list = ['r', 'i', 'n', 'g', 'i', 'n', 'g']
print to_string(a_list) # prints ringing
b_list = []
print to_string(b_list) # returns empty
Maybe a unique way of doing it.
#Python print() has a unique ability
List = ['a','b','c']
print(*List,sep="")
#### Output ####
abc
# In this method I'm trying to using python's print() ability
# and redirecting the print() from standard output to a temporary variable
# and then using it.
from io import StringIO # Python3
import sys
old_stdout = sys.stdout
result = StringIO() #store everything that is sent to the standard output
sys.stdout = result
print(*List, sep = "") #sends to variable result
#or do any fancy stuff here
sys.stdout = old_stdout # Redirect again the std output to screen
result_string = result.getvalue().strip() # strip() because it has \n at the end
print(result_string,type(result_string),len(result_string),sep="\n")
#this actually prints(), and also the result_string variable has that value
#### Output ####
abc
<class 'str'>
3
This will help you indetail. Store standard output on a variable in Python
Related
I have a predefined list with single quotes and I want double quotes in each element.
for example, this is my predefined list
l = ['A','b']
the output I needed as the list only
l = ["A","b"]
I am trying with json but it is giving list as a string but I want list.
import json
l = ['A','b']
output = json.dumps(l)
print(type(output))
There is no difference in your case. Try to print l:
l_double = ["A","b"]
l_single = ['A','b']
print(l_double)
print(l_single)
returns
['A', 'b']
['A', 'b']
In case you really want double quotes around you list items, try something like this:
l = ['A','b']
l_real_double = [f'"{c}"' for c in l]
print(l_real_double)
which prints
['"A"', '"b"']
L = ['A', 'B', 'C']
print('[', end='') #just to print the opening third bracket [
for i in range(len(L)): #the variable i will assume the values from 0 to length of L - 1 i.e. the indices of the elements
print('"' + L[i] + '"', end='') #display a double quote and the string inside it
if i < len(L)-1:
print(',', end=' ') #if i is not the index of the last element then display a comma after it
print(']') #just to print the closing third bracket ]
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'm going through Problem 3 of the MIT lead python course, and I have an admittedly long drawn out script that feels like it's getting close. I need to print the longest substring of s in which the letters occur in alphabetical order. I'm able to pull out any characters that are in alphabetical order with regards to the character next to it. What I need to see is:
Input : 'aezcbobobegghakl'
needed output: 'beggh'
my output: ['a', 'e', 'b', 'b', 'b', 'e', 'g', 'g', 'a', 'k']
My code:
s = 'aezcbobobegghakl'
a = 'abcdefghijklmnopqrstuvwxyz'
len_a = len(a)
len_s = len(s)
number_list = []
letter_list = []
for i in range(len(s)):
n = 0
letter = s[i+n]
if letter in a:
number_list.append(a.index(letter))
n += 1
print(number_list)
for i in number_list:
letter_list.append(a[i])
print(letter_list)
index_list = []
for i in range(len(letter_list)):
index_list.append(i)
print(index_list)
first_check = []
for i in range(len(letter_list)-1):
while number_list[i] <= number_list[i+1]:
print(letter_list[i])
first_check.append(letter_list[i])
break
print(first_check)
I know after looking that there are much shorter and completely different ways to solve the problem, but for the sake of my understanding, is it even possible to finish this code to get the output I'm looking for? Or is this just a lost cause rabbit hole I've dug?
I would build a generator to output all the runs of characters such that l[i] >= l[i-1]. Then find the longest of those runs. Something like
def runs(l):
it = iter(l)
try:
run = [next(it)]
except StopIteration:
return
for i in it:
if i >= run[-1]:
run.append(i)
else:
yield run
run = [i]
yield run
def longest_increasing(l):
return ''.join(max(runs(l), key=len))
Edit: Notes on your code
for i in range(len(s)):
n = 0
letter = s[i+n]
if letter in a:
number_list.append(a.index(letter))
n += 1
is getting the "number value" for each letter. You can use the ord function to simplify this
number_list = [ord(c) - 97 for c in s if c.islower()]
You never use index_list, and you never should. Look into the enumerate function.
first_check = []
for i in range(len(letter_list)-1):
while number_list[i] <= number_list[i+1]:
print(letter_list[i])
first_check.append(letter_list[i])
break
this part doesn't make a ton of sense. You break out of the while loop every time, so it's basically an if. You have no way of keeping track of more than one run. You have no mechanism here for comparing runs of characters against one another. I think you might be trying to do something like
max_run = []
for i in range(len(letter_list)-1):
run = []
for j in range(i, len(letter_list)):
run.append(letter_list[j])
if letter_list[j] > letter_list[j+1]:
break
if len(run) > len(max_run):
max_run = run
(Disclaimer: I'm pretty sure the above is off by one but it should be illustrative). The above can be improved in a lot of ways. Note that it loops over the last character as many as len(s) times, making it a n**2 solution. Also, I'm not sure why you need number_list, as strings can be compared directly.
What about a simple recursive approach :
data = 'ezcbobobegghakl'
words=list(data)
string_s=list(map(chr,range(97,123)))
final_=[]
def ok(list_1,list_2):
if not list_1:
return 0
else:
first = list_1[0]
chunks = list_2[list_2.index(first):]
track = []
for j, i in enumerate(list_1):
if i in chunks:
track.append(i)
chunks=list_2[list_2.index(i):]
else:
final_.append(track)
return ok(list_1[j:],list_2)
final_.append(track)
print(ok(words,string_s))
print(max(final_,key=lambda x:len(x)))
output:
['b', 'e', 'g', 'g', 'h']
You can find a list of all substrings of the input string, and then find all the strings that are sorted alphabetically. To determine of a letter is sorted alphabetically, sorted the original string by position in the alphabet, and then see if the final string equals the original string:
from string import ascii_lowercase as l
s = 'aezcbobobegghakl'
substrings = set(filter(lambda x:x, [s[i:b] for i in range(len(s)) for b in range(len(s))]))
final_substring = max([i for i in substrings if i == ''.join(sorted(list(i), key=lambda x:l.index(x)))], key=len)
Output:
'beggh'
This is one way of getting the job done:
s = 'aezcbobobegghakl'
l = list(s)
run = []
allrun = []
element = 'a'
for e in l:
if e >= element:
run.append(e)
element = e
else:
allrun.append(run)
run = [e]
element = e
lengths = [len(e) for e in allrun]
result = ''.join(allrun[lengths.index(max(lengths))])
"run" is basically an uninterrupted run; it keeps growing as you add elements bigger than what is previously seen ("b" is bigger than "a", just string comparison), and resets else.
"allrun" contains all "run"s, which looks like this:
[['a', 'e', 'z'], ['c'], ['b', 'o'], ['b', 'o'], ['b', 'e', 'g', 'g', 'h']]
"result" finally picks the longest "run" in "allrun", and merges it into one string.
Regarding your code:
It is very very inefficient, I would not proceed with it. I would adopt one of the posted solutions.
Your number_list can be written as [a.index(_) for _ in s], one liner.
Your letter_list is actually just list(s), and you are using a loop for that!
Your index_list, what does it even do? It is equivalent to range(len(letter_list)), so what are you aiming with the append in the loop?
Finally, the way you write loops reminds me of matlab. You can just iterate on the elements of a list, no need to iterate on index and fetch the corresponding element in list.
I am trying to extend an element to a list in Python, however, instead of extending the string in the index 'i' it extends every character of the string in the index 'i'.
For example I have a list called 'strings' with just a string 'string1' and an empty list called 'final_list'.
I want to extend the first element of 'strings' to the 'final_list', so I do final_list.extend(strings[0]). But instead of the 'final_list' to end with a length of 1, corresponding to the string inserted, the list ends up with a length of 7.
If it helps, this is my code:
con = connect()
i = 0
new_files = []
while i < len(files):
info_file = obter_info(con, files[i])
if info_file [5] == 0: #file not processed
new_files.append(files[i])
i += 1
Does anyone know how can I make this to work?
The extend method takes an iterable as an argument, unpacks that iterable and adds each element individually to the list upon which it is called. In your case, you are "extending" a list with a string. A string is an iterable. As such, the string is "unpacked" and each character is added separately:
>>> d = []
>>> d.extend('hello')
>>> print(d)
['h', 'e', 'l', 'l', 'o']
If you simply want to add one element of a list to another list, then use append. Otherwise, surround the string in a list and repeat the extend:
>>> d = []
>>> d.extend(['hello'])
>>> print(d)
['hello']
try that one:
final_list.extend([strings[0]])
or:
final_list.append(strings[0])
I need help with assigning lists in a recursive function. How can I assign a value to the ith member of a list when the recursive function is in ith iteration?
You can't change an iterable while using it to drive an iteration, but you could easily make an iterable to hold your results and pass it in to the recursive function as an argument:
results = []
def recurse(level, results):
level += 1
results.append(level)
if level < 10: recurse(level, results)
print recurse(0, results)
>>> [1,2,3,4,5,6,7,8,9,10]
but in this example you could not do
for item in results:
recurse (item, results)
I don't know if I'm understanding well your question, but I think it's something like:
# put "s" on 2nd position of the list ['l', 'u', 'c', 'a', 's']
# so the result should be ['l', 's', 'c', 'a', 's']
If so, keep in mind that there are better ways to do it in Python. So here's the code:
def assign_in_position(elem, my_list, pos):
first = my_list[0]
tail = my_list[1:]
if pos == 0:
return [elem] + tail
return [first] + assign_in_position(elem, tail, pos-1)
If you're new in Python there's only one thing that can be strange (slicing, my_list[1:]). This function is also kind of buggy, but it's proposital. It works for my first example, but if you're learning recursion, then you should learn how to detect and solve common recursion problems.
Out of curiosity, this is the Haskell code for the same task:
assign_in_pos elem [] _ = [elem]
assign_in_pos elem (_:t) 0 = elem:t
assign_in_pos elem (h:t) pos = h:assign_in_pos elem t (pos-1)