for looping and appending into list - python

list = []
def lecture(x):
for x in range(1,x):
print 'lecture', x
so I have this code that gives the result of
lecture 1
lecture 2
for an input of lecture(3). Now, when I change the code to
list = []
def lecture(x):
for x in range(1,x):
y = 'lecture', x
print y
i get an output of
('lecture', 1)
('lecture', 2)
Ultimately I would like to know why this is the case as I am trying to find a way of appending the first results, the:
lecture 1
lecture 2
into a list but I can't as I get a list with the lecture number separated from its number by a comma etc.

You are getting that strange notation because 'lecture', x is a tuple. A datatype which acts like a list, but a non-flexible list. You can't change them that easily. You have to use the +-operator instead of a comma to put those two values into one variable.
And putting values in a list is done with the append function.
list = []
def lecture(x):
for x in range(1,x):
y = 'lecture' + str(x)
list.append(y);
lecture(5)
Also note:
y = 'lecture' + str(x)
the str(x) is to make sure the different datatypes (int and string) don't conflict. Because String + Int ain't possible.
5 (Int) + 5 (Int) is 10.
5 (String) + 5 (String) is 55.
But 5 (String) + 5 (Int) is an error.

Swap y = 'lecture', x with:
y = 'lecture ' + str(x)
This will append the variable x to 'lecture' and set it in variable y

With the expression y = 'lecture', x, you are creating a tuple. Create an empty list instead, and append values to it with the for loop:
def lecture(x):
lecture_list=[]
for item in range(1,x+1):
y='lecture '+str(item)
lecture_list.append(y)
return lecture_list

An alternative way:
class Lectures(object):
def __init__(self, x):
self.x = x
def __iter__(self):
for i in range(1, self.x):
yield "lecture" + i
Here an iterable class Lectures is made.
First you need to initialize it, passing x as an attribute:
lectures = Lectures(x)
Then you can use it as an iterable:
list_of_lectures = list(lectures)
or
for lecture in lectures:
do_something

Related

New to python: query re string of length when it’s made up of repeated copies

I am a bit stuck, not sure what I’ve done wrong in my code as I am given what an output should be however I cannot get to it:
Write a function that takes two integers x and y, but this time produces a string of length y made up of repeated copies of x.
def repeat_int_length(x, y):
f = str(len('y') * x)
return f
repeat_int_length(10, 4)
The output I get is 10, but the instruction said it should have been 1010.
I believe that you have misunderstood the assignment.
...produces a string of length y
y here is an integer and it is the final length of the string that you will return. You do NOT have to calculate the length of the character y. y, the length, has been already passed as an argument.
Now for your task, this code shall work:
def repeat_int_length(x, y):
return (str(x) * y)[:y]
it will output:
1010
def repeat_int_length(x, y):
f = str(x) * y
return f[:y]
print(repeat_int_length(10, 4))
output
1010
It's called string slicing. It'll return a range of characters from a string.
syntax :string[start,end,step]
So in this case f[:y], characters starting from 0th index to yth index will be return.
If it's negative integer and you dont want - to be store : use abs()
def repeat_int_length(x, y):
f = str(abs(x)) * y
return f[:y]
print(repeat_int_length(-10, 5))
Output:
10101
If I understood the instructions correctly...
def repeat_int_length(x, y):
f= ""
while len(f) < y:
f = f + str(x)
return f
repeat_int_length(10, 4)
Without knowing the other inputs, its tough to say....
With repeat_int_length(10, 4) you get 1010
However, what about weird cases where you get longer inputs:
repeat_int_length(101, 4) = 101101, if you strictly need to provide y length, then you would need to trim that answer(assuming they meant to keep the first part only):
def repeat_int_length(x, y):
f= ""
while len(f) < y:
f = f + str(x)
return f[:y]
repeat_int_length(101, 4)
Also, x doesn't need to be an integer, it can be a string, for example:
repeat_int_length("Hello", 10) --> HelloHello
Try repeating str(x) y//len(str(x))+1 number of times and return only the first y characters.
def repeat_int_length(x, y):
return (str(x)*(y//len(str(x))+1))[:y]
y//len(str(x)) gives you how many times the total length y is divisible by the length of x.
Add one in case they are not perfectly divisible.
Return only the first y characters of the result using [:y]
def repeat_int_length(x, y):
x=str(x)
s=str(x)
q,r = divmod(y,len(s))
return s*q+x[:r]
print( repeat_int_length(10, 9))
You have to find out how many times you want to multiply your string.

Store the output of a function into a variable

I have the following function that returns data:
def get_comments():
for i in data:
comment_data = i['comments']
for z in comment_data:
comments = comment_data['data']
for j in comments:
comment = j['message']
print(comment)
I would like to save the output of this function to a variable. I'm using print instead of return (in the function get_comments) since, return only returns the final row of my data. This is what i have tried to account for that:
def hypothetical(x):
return x
z = hypothetical(get_comments())
print(z)
However the output of the variable z is "None".
When i try some other value(i.e.):
z = hypothetical(5)
print(z)
z is equal to 5 of course.
Thanks
Instead of printing each line, you need to add it to a different data structure (such as a list) and return the whole list at the end of get_comments().
For example:
def get_comments():
to_return = []
for i in data:
comment_data = i['comments']
for z in comment_data:
comments = comment_data['data']
for j in comments:
comment = j['message']
to_return.append(comment)
return to_return
If you want to get a bit more advanced, you can instead create a generator using yield:
def get_comments():
for i in data:
comment_data = i['comments']
for z in comment_data:
comments = comment_data['data']
for j in comments:
comment = j['message']
yield comment
Then you can iterate over get_comments() and it will go back into the generator each time to get the next comment. Or you could simply cast the generator into a list with list(get_comments()) in order to get back to your desired list of comments.
Refer to this excellent answer for more about yield and generators.

Pyparsing parseaction and lists typerror

For a small language I want to parse expressions of the form "X [Y,Z,V]" where X, Y, Z, V are natural numbers.
Below is my attempt.
from pyparsing import *
class Y():
def __init__(self, ls):
self.ls = ls
def MakeCombinedList(tokens):
print(len(tokens)) # prints 4
print(tokens) # [5, 1, 2, 3]
clist = tokens[1]
clist.append(tokens[0]) # 'int' attribute object has no attribute 'append'
return clist
def MakeIntList(tokens):
nlist = tokens[0].split(",")
ilist = []
for n in nlist:
ilist.append(int(n))
return ilist
def MakeY(tokens):
Yobj = Y(tokens[0])
return Yobj
LEFT_BRACK = Suppress(Literal("["))
RIGHT_BRACK = Suppress(Literal("]"))
NATURAL = Word(nums).addParseAction(lambda n: int(n[0]))
NATURAL_LIST = delimitedList(NATURAL, combine = True)
NATURAL_VEC = LEFT_BRACK + NATURAL_LIST + RIGHT_BRACK
NATURAL_VEC.addParseAction(MakeIntList)
X = NATURAL + NATURAL_VEC
X.addParseAction(MakeCombinedList)
Y = X
Y.addParseAction(MakeY)
print(Y.parseString("5 [1,2,3]").ls)
MakeIntList is supposed to transform a string such as "1,2,3" into the list [1,2,3].
MakeCombinedList is then supposed to append an integer to this list, but the tokens received by MakeCombinedList are not the single integer and the integer list created from MakeIntList, but a list of all the integers, as indicated by my comment.
How can I make tokens[1] inside MakeCombinedList be the result of calling MakeIntList?
These two lines are working against each other, since you use the first to parse separate numeric strings into ints, and then the second just combines them back into a comma-separated string.
NATURAL = Word(nums).addParseAction(lambda n: int(n[0]))
NATURAL_LIST = delimitedList(NATURAL, combine=True)
The feature you are looking for is Group:
NATURAL = Word(nums).addParseAction(lambda n: int(n[0]))
NATURAL_LIST = Group(delimitedList(NATURAL))
NATURAL_VEC = LEFT_BRACK + NATURAL_LIST + RIGHT_BRACK
# no MakeIntList parse action required
Now instead of creating a new string and then re-parsing it in a parse action, you use Group to tell pyparsing to make a sub-structure of the resulting tokens.
There is also a little confusion going on here:
Y = X
Y.addParseAction(MakeY)
This will redefine Y from the class defined at the top to a pyparsing expression, and you get some weird traceback when trying to accessing its ls attribute.
Y_expr = X
Y_expr.addParseAction(MakeY)
I wrote the runTests method to make it easier to do simple expression testing and printing, without having to deal with Py2/Py3 print differences:
Y_expr.runTests("""\
5 [1,2,3]
""")
Shows:
5 [1,2,3]
[<__main__.Y object at 0x00000241C57B7630>]
Since your Y class just uses the default __repr__ behavior, you can see the contents better if you define your own:
class Y():
def __init__(self, ls):
self.ls = ls
def __repr__(self):
return "{}: {}".format(type(self).__name__, vars(self))
Now runTests shows:
5 [1,2,3]
[Y: {'ls': 5}]
If the purpose of the Y class is to just give you attribute names for your parsed fields, consider using results names instead:
X = NATURAL('ls') + NATURAL_VEC
Y_expr = X
#~ Y_expr.addParseAction(MakeY)
# what you had written originally
print(Y_expr.parseString("5 [1,2,3]").ls)
Will just print:
5

Simple list function in Python

I am trying to append values (x) to a list if the numbers are divisible by 2 and then print out that list. Seems pretty simple. The following runs but returns None:
x = []
def test():
while x in range(0,100):
if x % 2 == 0:
x.append()
print(test())
Use for to iterate a range - not while.
You have ambiguous meaning to x - both as iteration variable and as a list.
You need to pass the value to append.
You need to return a value so it would be printed through the print statement - otherwise None is the default.
Fixed:
x = []
def test():
for i in range(0,100):
if i % 2 == 0:
x.append(i)
return x
print(test())
Other notes:
You can only use this once. The next call for test would return a list twice the size, since x is a global variable. I believe this is unintended and can be solved by putting the x = [] inside the function.
A list comprehension like [x for x in range(100) if x % 2 == 0] would be much better.
Problems and Fixes
Your have several problems with your code:
You named your list x and your iterate variable x.
You never append a value to your list.
You never return a list from test. Rather than appending to a global list, make a local list in test and return that list.
You're using a while loop when you should be using a for loop.
After the above changes, you code look likes:
def test():
even_numbers = []
for number in range(0, 100):
if number % 2 == 0:
even_numbers.append(number)
return even_numbers
print(test())
Improvements
Note there are better ways to do this. In this case, a list comprehension is a better choice. List comprehensions can be used to avoid the common pattern of building a list of values - such as your case:
def test():
return [n for n in range(0, 100) if n % 2 == 0]
print(test())
Generally you should pass the variable to the function and return it from the function instead of relying on global variables:
def test(x):
...
return x
However while x in range(0, 100) won't work because it will check if x (an empty list) is contained in the range object. But the range only contains numbers so the while loop body will never execute. So you could use a for-loop instead:
def test(x):
for i in range(0, 100):
if i % 2 == 0:
x.append(i)
return x
But you could also use the fact that range supports a step and remove the if by just using step=2:
def test(x):
for i in range(0, 100, 2):
x.append(i)
return x
At this point you could even just extend (append an iterable to) the list:
def test(x):
x.extend(range(0, 100, 2))
return x
You could also use a step of 2 to avoid if tests :
x = []
def test():
for i in range(0,100,2):
x.append(i)
return x
Or use a list comprehension :
x = []
def test():
x = [i for i in range(0,100,2)]
return x
Or use the range it's self as a list:
x = []
def test()
x = list(range(0,100,2))
return x
Rename your inner x variable for simplicity. Use x.append(n) instead of x.append(). Finally, print the variable not the method.
You should either change the list variable or the iteration variable(x in while loop) . and append function works like this list.append(value).

Calculating the value of integers in list

I have a list with int values that I would like to add to each other and log the end value. So far I could create a working solution, but it's not so elegant and I would be happy if somebody could show me a smarter solution to achieve the same result.
numberList = (list(string_dict.values()))
numz = []
placeholder = 0
for x in numberList:
numz.append(int(x))
for y in numz:
placeholder = placeholder + y
print (placeholder)
# [1,2,3]
# result: 6
You can use the sum function:
print(sum(int(x) for x in string_dict.values()))
You can take out both loops by using the map() and sum() functions:
numberList = list(string_dict.values())
numz = []
placeholder = 0
numz = list(map(int, numberList))
placeholder = sum(numz)
print (placeholder)
You don't really need to have numberList and numz in there, though. Just do this:
placeholder = sum(map(int, string_dict.values()))
You can use reduce function also:
from functools import reduce
print reduce( (lambda x, y: x + y), string_dict.values() )

Categories