I am having issues with creating a function that takes a list of tuples and then returns one string which is the first character of each tuple. Below is my current code, but nothing it happening, I do not get a syntax error. Any help would be appreciated.
lst_of_tups = ([('hello', 'all'), ('music', 'playing'), ('celebration', 'station')])
def build_string(lst_of_tups):
final_str = ""
for tup in list_of_tups:
for item in tup:
final_str = final_str + item[0]
return final_str
print build_string
**** expected output: hampcs****
those string manipulation functions are error-prone: they define lots of variables, can return within inner loops, have unexpected side-effects...
Once you're used to list comprehensions, you can create such programs easily & with great execution performance (string concatenation is slow). One way:
def build_string(lst_of_tups):
return "".join([x[0] for y in lst_of_tups for x in y])
basically, it's just 2 loops (flattening the data) within a list comprehension to extract each first character from every string, joined together using str.join to rebuild the string.
Once you reach a return statement in a function, the function ends for good. The line
print build_string
cannot be reached. (Another problem is that the name build_string is not defined.)
Use your function like this:
result = build_string(lst_of_tups) # calls your function and puts the return value in the result variable
print result # print the result
Of course, the intermediary variable result is not necessary, you could just issue print build_string(lst_of_tups) as well.
Related
I am trying to create a function named make_string, that uses * correctly with a parameter: strings
The function should return a string of all the values supplied joined, and separated by a space.
Outside the make_string function, I declare a variable named my_string, and assign the value returned from the make_string function.
Then I call the make_string function with the following values: "Alderaan", "Coruscant", "Dagobah", "Endor", "Hoth". Finally I print the value of my_string to the terminal...and it returns None, when it should return Alderaan Coruscant Dagobah Endor Hoth
Can anybody tell me where I am going wrong please?
def make_string(*strings):
my_string = ""
for x in strings:
my_string = x.join(strings)
return my_string
my_string = make_string()
make_string("Alderaan", "Coruscant", "Dagobah", "Endor", "Hoth")
print(my_string)
There are a few things going on in your code that are a little wonky.
You're constantly re-assigning the value of my_string every time you loop through for x in strings
There's no reason to start with a blank string here since you're already using join
Your function call isn't setting to my_string -- it isn't set to anything. What you want is like my_string = make_string("Bob", "Mary") etc.
This should do the trick:
def make_string(*strings):
return " ".join(strings)
my_string = make_string("Alderaan", "Coruscant", "Dagobah", "Endor", "Hoth")
print(my_string)
Personally, I would say you don't even need a function here, especially if you can easily set what you're using for *strings to a variable. For example:
planets = ["Alderaan", "Coruscant", "Dagobah", "Endor", "Hoth"]
print(" ".join(planets))
I have this string delimited by commas.
'1.0,5.0,6.0,7.0,8.0,9.0'
def var():
for i in listnumbers:
return i +'.0'
When I do
var()
I only get
1.0
How do i get the result to include all the numbers in a loop?
1.0,5.0,6.0,7.0,8.0,9.0
def myfun(mycsv):
return [i+'.0' for i in mycsv.split(',')]
print(myfun('1.0,5.0,6.0,7.0,8.0,9.0'))
#['1.0.0', '5.0.0', '6.0.0', '7.0.0', '8.0.0', '9.0.0']
If you want a string, then just use join:
print(','.join(myfun('1.0,5.0,6.0,7.0,8.0,9.0')))
Or change the function to return a string;
return ','.join([i+'.0' for i in mycsv.split(',')])
You are returning inside the for loop, before the cycle is completed.
If I understood correctly your question, it looks like what you're looking for is list comprehension.
If your input is a list:
def var(l):
return [i + '.0' for i in l]
If your input is a string, like it seems from your description, you have to split it first:
def var(l):
return [i + '.0' for i in l.split(',')]
This is equivalent to mapping in other languages.
You can divide your string in a list using string.split(',') the you iterate over the freshly created list and print each element. A the code can be arranged like this:
for s in string.split(','):
print(s+'.0')
ts_file = "ts_nfl_04_red_zone_conversion"
ts_title = [print(i + ' ', end="") for i in ts_file[7:].upper().split("_")]
Result:
04 RED ZONE CONVERSION [None, None, None, None]
What produce this list of None statement and how I can avoid it?
Many thanks.
You can use replace instead:
>>> ts_file[7:].upper().replace("_", " ")
You could instead join the elements resulting from the splitting the string:
ts_title = (' ').join(ts_file[7:].upper().split("_"))
# '04 RED ZONE CONVERSION'
List comprhension isn't really necessary here as a print statement returns a None type. You can just loop through the string like this:
for i in ts_file[7:].upper().split("_"): print(i + " ", end="")
You produced a list of None because you created one. That's what a list comprehension is for: creating lists. However, expressions aren't automatically printed unless you're in the interactive interpreter and have returned the expression to the top level, which means you wouldn't actually see this output given that you're saving it to a variable.
Anyway, you're supposed to use a regular loop in this situation, as follows:
ts_file = "ts_nfl_04_red_zone_conversion"
for i in ts_file[7:].upper().split("_"):
print(i + ' ', end="")
However, you can of course still use a comprehension and create an empty list by rearranging it slightly, saving it to a variable so that it isn't automatically printed in the interactive interpreter:
ts_file = "ts_nfl_04_red_zone_conversion"
ts_title = [None for i in ts_file[7:].upper().split("_") if print(i + ' ', end="")]
As mentioned in the comments, print returns a None and is not intended be used in a list comprehension.
if you want a one-liner to achieve your desired result, you can do something like
print(' '.join(ts_file[7:].upper().split("_")))
As mentioned by others, print() does not return anything. Hence, None is printed. If you are wondering why the elements are properly printed, and then followed by 4 None's, its because of how functions work.
A function is called and once every statement inside has been executed, a value is returned, but only if the function returns something.
In your case, print(i + ...) called the print function on i, print was executed, meaning that it printed i to the console, and then its value was returned, which is None, since print() does n't return anything.
Coming to the solution, you could use the .join() method or the replace() method:
a = ts_file[7:].upper().replace("_", " ")
print(a)
or
a = (' ').join(ts_file[7:].upper().split("_"))
print(a)
The output:
04 RED ZONE CONVERSION
You could also do another thing, if you did n't care about what was stored in ts_title:
As soon as you assign ts_title with your list comprehension:
ts_title = [print(i + ' ', end="") for i in ts_file[7:].upper().split("_")]
if you run your script, you will get the expected output on the screen, just as I had explained at the start of the answer.
So this is what I'm trying to do:
input: ABCDEFG
Desired output:
***DEFG
A***EFG
AB***FG
ABC***G
ABCD***
and this is the code I wrote:
def loop(input):
output = input
for index in range(0, len(input)-3): #column length
output[index:index +2] = '***'
output[:index] = input[:index]
output[index+4:] = input[index+4:]
print output + '\n'
But I get the error: TypeError: 'str' object does not support item assignment
You cannot modify the contents of a string, you can only create a new string with the changes. So instead of the function above you'd want something like this
def loop(input):
for index in range(0, len(input)-3): #column length
output = input[:index] + '***' + input[index+4:]
print output
Strings are immutable. You can not change the characters in a string, but have to create a new string. If you want to use item assignment, you can transform it into a list, manipulate the list, then join it back to a string.
def loop(s):
for index in range(0, len(s) - 2):
output = list(s) # create list from string
output[index:index+3] = list('***') # replace sublist
print(''.join(output)) # join list to string and print
Or, just create a new string from slices of the old string combined with '***':
output = s[:index] + "***" + s[index+3:] # create new string directly
print(output) # print string
Also note that there seemed to be a few off-by-one errors in your code, and you should not use input as a variable name, as it shadows the builtin function of the same name.
In Python, strings are immutable - once they're created they can't be changed. That means that unlike a list you cannot assign to an index to change the string.
string = "Hello World"
string[0] # => "H" - getting is OK
string[0] = "J" # !!! ERROR !!! Can't assign to the string
In your case, I would make output a list: output = list(input) and then turn it back into a string when you're finished: return "".join(output)
In python you can't assign values to specific indexes in a string array, you instead will probably want to you concatenation. Something like:
for index in range(0, len(input)-3):
output = input[:index]
output += "***"
output += input[index+4:]
You're going to want to watch the bounds though. Right now at the end of the loop index+4 will be too large and cause an error.
strings are immutable so don't support assignment like a list, you could use str.join concatenating slices of your string together creating a new string each iteration:
def loop(inp):
return "\n".join([inp[:i]+"***"+inp[i+3:] for i in range(len(inp)-2)])
inp[:i] will get the first slice which for the first iteration will be an empty string then moving another character across your string each iteration, the inp[i+3:] will get a slice starting from the current index i plus three indexes over also moving across the string one char at a time, you then just need to concat both slices to your *** string.
In [3]: print(loop("ABCDEFG"))
***DEFG
A***EFG
AB***FG
ABC***G
ABCD***
In web2py I have been trying to break down this list comprehension so I can do what I like with the categories it creates. Any ideas as to what this breaks down to?
def menu_rec(items):
return [(x.title,None,URL('shop', 'category',args=pretty_url(x.id, x.slug)),menu_rec(x.children)) for x in items or []]
In addition the following is what uses it:
response.menu = [(SPAN('Catalog', _class='highlighted'), False, '',
menu_rec(db(db.category).select().as_trees()) )]
So far I've come up with:
def menu_rec(items):
for x in items:
return x.title,None,URL('shop', 'category',args=pretty_url(x.id, x.slug)),menu_rec(x.children))
I've got other variations of this but, every variation only gives me back 1(one) category, when compared to the original that gives me all the categories.
Can anyone see where I'm messing this up at? Any and all help is appreciated, thank you.
A list comprehension builds a list by appending:
def menu_rec(items):
result = []
for x in items or []:
url = URL('shop', 'category', args=pretty_url(x.id, x.slug))
menu = menu_rec(x.children) # recursive call
result.append((x.title, None, url, menu))
return result
I've added two local variables to break up the long line somewhat, and to show how it recursively calls itself.
Your version returned directly out of the for loop, during the first iteration, and never built up a list.
You don't want to do return. Instead append to a list and then return the list:
def menu_rec(items):
result = []
for x in items:
result.append(x.title,None,URL('shop', 'category',args=pretty_url(x.id, x.slug)),menu_rec(x.children)))
return result
If you do return, it will return the value after only the first iteration. Instead, keep adding it to a list and then return that list at the end. This will ensure that your result list only gets returned when all the values have been added instead of just return one value.