Print inside lambda - python

I'm currently using syntax like this:
print(*list(map(lambda a: [something to do], input())))
It's working fine if the return type is a string but not for a number.
For example. The below script is for finding the square root of three in two different version
print(*list(map(lambda a: int(a)**(1/3), input())))
and
SQRT = lambda a: a**(1/3)
print(SQRT(int(input())))
When I input 9 both return 2.080083823051904 (Which is correct) but when I input 10 the first one return 1.0 0.0 and 2.154434690031884 for the second one.
I wanted to know that is there any way I can print directly from lambda that returns a number without causing a problem addressed above?

You are focusing on the wrong issue here. This is not a problem with printing; removing the print() function from the equation will give you the same results.
You are iterating over the individual characters of the input string, producing the cube root of 1 and 0 respectively when entering '10' into the input prompt, or of 9 when you enter '9':
>>> list(map(lambda a: int(a)**(1/3), '10'))
[1.0, 0.0] # [1 ** (1/3), 0 ** (1/3)]
>>> list(map(lambda a: int(a)**(1/3), '9'))
[2.080083823051904] # [9 ** (1/3)]
input() returns a string object, and strings are iterables; a sequence of the individual characters. For '10' iteration gives you '1' and '0':
>>> list('10') # just iteration, pulling out the separate parts
['1', '0']
Your second code snippets applies int() to the whole input() string, so then you get the square root of 10 and 9:
>>> SQRT(int('10'))
2.154434690031884
>>> SQRT(int('9'))
2.080083823051904
If you wanted the cube root of the input, don't use map():
>>> CBRT = lambda a: a ** (1/3)
>>> CBRT(int('10'))
>>> CBRT(int('10'))
2.154434690031884
Side note: * works on any iterable, including the iterator object that map() produces, so print(*map(...)) works just as well as print(*list(map(...))), but without creating a list object first that then is discarded again.

By using map on the returning string of input(), you are treating the string as a sequence of individual characters, and hence the cube root of 1 and 0 when you input '10'.
You should use the second method you posted, since the all the lambda, map, and unpacking add no value to the problem you're solving.

Related

Problems with 'lambda' expression in python

I have the following problem solving question
Please write a program using generator to print the even numbers
between 0 and n in comma separated form while n is input by console.
Example: If the following n is given as input to the program: 10 Then,
the output of the program should be: 0,2,4,6,8,10.
And below is my answer
n=int(input("enter the number of even numbers needed:"))
eve=''
st=(lambda x:(for i in range(0,x))[(str(i)) if i%2==0 else (",")])(n)
However, I have a problem with the third line that has the lambda
Take full advantage of Python 3's features to create a generator using generator expression syntax, also do the even number stepping with range()'s third paramter.
This would be much briefer:
>>> n = 12
>>>
>>> fn = lambda x: (f"{i}," for i in range(0, x + 1, 2))
>>>
>>> ''.join(list(fn(n)))[:-1] + '.'
'0,2,4,6,8,10,12.'
>>>
>>> fn(10)
<generator object <lambda>.<locals>.<genexpr> at 0x107f67660>
What looks like a tuple comprehension is actually called a "generator expression". Note that in the last line above the interpeter is indicating that the type returned by the lambda is indeed a generator.
Even briefer, you could do it this way:
>>> fn = lambda x: ','.join( (f"{i}" for i in range(0, x + 1, 2)) ) + '.'
>>>
>>> fn(n)
'0,2,4,6,8,10,12.'
>>>
Looks like you might have been on the right track in your question post.
A function that uses the yield keyword also creates a generator. So the other poster is correct in that regard.

inputted list keeps being interpreted as string

So I made this little code at school, and i know that input() can understand lists as is. I tried it again at home but it doesnt work. My school computer has python 2. something while my laptop has 3.4.
The code looks like this
a = input()
list = []
count = 0
for y in range(1, len(a)):
min = a[count]
for x in range(count +1, len(a)):
if min > a[x]:
min = a[x]
print(min)
a[count] = min #str object does not support item assignment
count=count+1
print (a)
I want to input a list such as [1,2,3,4,5] but what happens is, it reads the whole thing as a string, along with the commas, when i want to see it as a list of integers.
Python 3's input returns a string (same as Python 2's raw_input), whilst Python 2's input evaluates the text. To get similar behaviour, if you've got a valid Python list that can be evaluated, then you can use ast.literal_eval, eg:
import ast
a = ast.literal_eval(input())
# do other stuff with `a` here...
So you'd enter something like [1, 2, 3, 4, 5] as your input, and you'll end up with a being a Python list.
I assume your input would be something like: "1 2 3 4 5" -- judging by the code which comes later. This oufcourse is a string. If you want to work with the numbrs in the string as integers you need to:
a = input()
a = map(int, a.split())

Create variables dynamically inside 'for' loop

I'm new to python and trying to take some coding challenges to improve my skills. I've to take input in following ways:
2
3 1
4 3
First, I get number of test cases.(2 here) Then based on that, I've to get given number of test cases that are each 2 integers. 1st is the range and second is the number to be searched in the range.
What's the correct, pythonic way of getting the input. I was thinking like this but it's obviously incorrect
num_testcases = int(raw_input())
for i in num_testcases:
range_limit = int(raw_input())
num_to_find = int(raw_input())
raw_input() is going to be read one line at a time from STDIN, so inside the loop you need to use str.split() to get the value of range_limit and num_to_find. Secondly you cannot iterate over an integer(num_testcases), so you need to use xrange()(Python 2) or range()(Python 3) there:
num_testcases = int(raw_input())
for i in xrange(num_testcases): #considering we are using Python 2
range_limit, num_to_find = map(int, raw_input().split())
#do something with the first input here
Demo:
>>> line = '3 1'
>>> line.split()
['3', '1']
>>> map(int, line.split())
[3, 1]
Note that in Python 3 you'll have to use input() instead of raw_input() and range() instead of xrange(). range() will work in both Python 2 and 3, but it returns a list in Python 2, so it is recommended to use xrange().
Use for i in range(num_testcases): instead of for i in num_testcases. Have a look at range (or xrange in Python 2). range(a) produces an iterable from 0 to a - 1, so your code gets called the desired number of times.
Also, input and raw_input take input on encountering a newline, meaning that in range_limit = int(raw_input()), raw_input returns "3 1", which you can't just convert to int. Instead, you want to split the string using string.split and then convert the individual items:
num_testcases = int(raw_input())
for i in range(num_testcases):
range_limit, num_to_find = [int(x) for x in raw_input().split()]

Adding slicing numbers using a loop

I want to know how can I add these numbers in Python by using a loop? Thanks
num=input("Enter your number: ")
ansAdd= int(str(num)[7])+int(str(num)[5])+int(str(num)[3])+int(str(num)[1])
print....
you want to do it using a loop, here you go:
ansAdd = 0
for x in [7,5,3,1]:
ansAdd += int(str(num)[x])
However, using list comprehension is more pythonic
>>> s = '01234567'
>>> sum(map(int, s[1::2]))
16
Here is how it works:
s[1::2] takes a slice of the string starting at index 1 to the end of the string stepping by 2. For more information on slices see the Strings section of the Python Tutorial.
map takes a function and an iterable (strings are iterable) and applies the function to each item, returning a list of the results. Here we use map to convert each string-digit to an int.
sum takes an iterable and sums it.
If you want to do this without the sum and map builtins, without slices, and with an explicit for-loop:
>>> s = '01234567'
>>> total = 0
>>> for i in range(1, len(s), 2):
... total += int(s[i])
...
>>> total
16
>>> num=input()
12345678
>>> sum(map(int,num[:8][1::2]))
20
here num[:8][1::2] returns only the numbers required for sum(), num[:8] makes sure only the elemnets up to index 7 are used in calculation and [1::2] returns 1,3,5,7
>>> num[:8][1::2]
>>> '2468'
It seems you want to sum odd-numbered digits from user input. To do it with a loop:
num_str = raw_input("Enter your number: ")
ansAdd = 0
for digit in num_str[1::2]:
ansAdd += int(digit)
(The syntax [1::2] is python's string slicing -- three numbers separated by : that indicates start index, stop index and step. An omitted value tells python to grab as much as it can.)
There's a better way to do this without using a traditional loop:
num_str = raw_input("Enter your number: ")
ansAdd = sum(int(digit) for digit in num_str[1::2])
In python 2, input executes the entered text as python code and returns the result, which is why you had to turn the integer back into a string using str.
It is considered a security risk to use input in python 2, since the user of your script can enter any valid python code, and it will be executed, no questions asked. In python 3 raw_input has been renamed to input, and the old input was removed (use eval(input()) instead).

Using any in re.findall - Python

I wrote a script in python to tell which numbers in new were in the first 10 numbers in new. I know it looks more complicated than it has too and that has to do with what I'm trying to do with the script later. For now though I'm trying to figure out why it's printing 'each' for EVERY number in the list 'new' and not just the ones before the tenth.
Here's my code:
i = 10
new = ['A lot of numbers']
for each in re.findall(r'[0-9]+', new):
if any(each for x in (re.findall(r'[0-9]+', new)[0:i])):
print each
else:
pass
You need to refer to x somehow in your generator expression, or else you're just checking any([each, each, each, ....]), which will always evaluate to true if each evaluates to true (which it always will for your regular expression). I suspect you want something like this, which tests if any of the first i items is equal to each:
if any(x==each for x in (re.findall(r'[0-9]+', new)[0:i])):
If you're looking for the first 10 letters in new, did you mean
if any(each for x in (re.findall(r'[0-9]+', new[0:i]))):
rather than:
if any(each for x in (re.findall(r'[0-9]+', new)[0:i])):
Also, did you mean for new to be a list? A list can't be passed to findall.
Finally, note that you never need an else: pass statement, an if works fine on its own.
If new is a list of strings, some of which are numbers like "123", and you want the first 10 of these numbers:
allnumbers = [x for x in new if re.match("[0-9]+", x)]
first10numbers = allnumbers[:10]
(For Python 2.x)
If new is a string, you'd have
allnumbers = [x for x in re.findall("[0-9]+", x)]
I'm not exactly sure what you're doing with this later, but if you're just trying to print the later numbers only if they show up in the first 10 numbers, you might just go like:
for number in [x for x in allnumbers if x in first10numbers]:
print number

Categories

Resources