def largestNumber(self, num):
num = [str(x) for x in num]
num.sort(cmp=lambda x, y: cmp(y+x, x+y))
return ''.join(num).lstrip('0') or '0'
What I would like to know is what is exactly is happening in the num.sort line where the lambda function takes in an x and y and does this cmp() function. This is the specific question that the code is being used for if anyone wants to see this as well https://leetcode.com/problems/largest-number/#/description
I'd recommend you to use Visualize python with the following code:
class Solution:
def largestNumber(self, num):
num = [str(x) for x in num]
num.sort(cmp=lambda x, y: cmp(y+x, x+y))
return ''.join(num).lstrip('0') or '0'
print Solution().largestNumber([4,6,2,7,8,2,4,10])
To get the concept clear,
num = [str(x) for x in num]
This takes every element of list num as x and converts it to a string and the result list is stored as num
num.sort(cmp=lambda x, y: cmp(y+x, x+y))
cmp:
cmp(x, y)ΒΆ
Compare the two objects x and y and return an integer according to the outcome. The return value is negative if x < y, zero if x == y and
strictly positive if x > y.
Lambda Expression:
Small anonymous functions can be created with the lambda keyword. This
function returns the sum of its two arguments: lambda a, b: a+b.
Hope this helps!
Yes, the lambda function does exactly the comparisons you suggest: "998" to "989", etc. This way, the list items are sorted into lexicographic order, largest first. You have to worry about the concatenated combinations to get the proper order for largest numbers: '9' vs '98' is a typical example of why you need concatenation, as you want "998" in the result.
Related
This is a question from a school assignment, and appreciate any assistance in pointing out my mistake.
First of all, with respect to the map() function in Python, I have been tasked (non-optionable) to redefine it as such to make it specific to a tuple:
def map(fn, seq):
if seq == ():
return ()
else:
return (fn(seq[0]),) + map(fn, seq[1:])
Using this, I am supposed to define another function square_odd(tuple) that takes in a tuple containing integers as an argument, and specifically square the terms only if they are odd. Essentially, for a tuple input of (5,6,7,8,9), I should be returned (25, 6, 49, 8, 81).
My idea is simply to utilise lambda to write a function, paired with an if to filter out the odd numbers. Here's what I have:
def square_odd(tpl):
return map(lambda x: x*x if x%2 == 0, tpl)
Python has returned me a SyntaxError at the comma before tpl. Can anyone point out what may be the issue with this? Must I write an else condition as well? I have tried adding else x but I am only returned the integer value of the first value.
That's because you should write else statement.
map(lambda x: x*x if x%2 == 1 else x, tp1)
and tried this code as simple. And also you should fixed x%2 == 0.
This condition will find even number.
return tuple(map(lambda x: x*x if x%2 == 1 else x, tp1))
if with lambda expects an else statement. So it should be like this:
def square_odd(tpl):
return map(lambda x: x if x%2 == 0 else x*x, tpl)
Which means, take x if x%2==0 i.e. if it is even, else take x*x which is it's square.
def map(fn, seq):
if seq == ():
return ()
else:
return (fn(seq[0]),) + map(fn, seq[1:])
def square_odd(tpl):
return map(lambda x: x**2 if x%2 else x, tpl)
t = (1,2,3,4,5)
print(square_odd(t))
I have done this and the output is (1, 2, 9, 4, 25).
PS the syntax error raise because the ternary operator A if condition else B cannot be used as A if condition
I'm kinda new to Programming and Python and I'm self learning before going to uni so please be gentle, I'm a newbie. I hope my english won't have too many grammatical errors.
Basically I had this exercise in a book I'm currently reading to take a list of tuples as a function parameter, then take every item in the each tuple and put it to 2nd power and sum the items up.
My code looks like this and works good if my function call includes the same amount of arguments as the function for loop requires:
def summary(xs):
for x,y,z in xs:
print( x*x + y*y + z*z)
xs =[(2,3,4), (2,-3,4), (1,2,3)]
summary(xs)
However, If I use a list with less tuples than the function definition, I get an error: ValueError : not enough values to unpack(expected 3, got 0):
xs =[(2,3,4), (), (1,2,3)]
I would like to know how to make a function that would accept a tuple I shown before () - with no tuples, and the function would return 0. I have been trying multiple ways how to solve this for 2 days already and googling as well, but it occurs to me I'm either missing something or I'm not aware of a function i could use. Thank you all for the help.
One way is to iterate over the tuple values, this would also be the way to tackle this problem in nearly every programming language:
def summary(xs):
for item in xs:
s = 0
for value in item:
s += value**2
print(s)
Or using a list comprehension:
def summary(xs):
for item in xs:
result = sum([x**2 for x in item])
print(result)
also note that sum([]) will return 0 for an empty iterable.
Well, the issue is that you don't have enough indices in your inner tuple to unpack into three variables. The simplest way to go around it is to manually unpack after checking that you have enough variables, i.e.:
def summary(xs):
for values in xs:
if values and len(values) == 3:
x, y, z = values # or don't unpack, refer to them by index, i.e. v[0], v[1]...
print(x*x + y*y + z*z)
else:
print(0)
Or use a try..except block:
def summary(xs):
for values in xs:
try:
x, y, z = values # or don't unpack, refer to them by index, i.e. v[0], v[1]...
print(x*x + y*y + z*z)
except ValueError: # check for IndexError if not unpacking
print(0)
One way is to use try / except. In the below example, we use a generator and catch occasions when unpacking fails with ValueError and yield 0.
While you are learning, I highly recommend you practice writing functions which return or yield rather than using them to print values.
def summary(xs):
for item in xs:
try:
yield sum(i**2 for i in item)
except ValueError:
yield 0
xs = [(2,3,4), (), (1,2,3)]
res = list(summary(xs))
print(res)
[29, 0, 14]
Or to actually utilise the generator in a lazy fashion:
for i in summary(xs):
print(i)
29
0
14
You should use the "len > 0" condition. This code should work for any list or tuple length :
def summary(xs):
for tup in xs:
prod = [a*a for a in tup if len(tup)>0]
print(sum(prod))
Note that I defined a "prod" list in order to use "sum" so that it is not calculated the hard way. It replaces your "x* x + y* y + z* z" and works for any tuple length.
It often pays to separate your algorithm into functions that just do one thing. In this case a function to sum the squares of a list of values and a function to print them. It is very helpful to keep your variable names meaningful. In this case your xs is a list of lists, so might be better named xss
import math
def sum_of_squares(xs):
return sum(map(math.sqr, xs))
def summary(xss):
for xs in xss:
print sum_of_squares(xs)
xss = [(2,3,4), (), (1,2,3)]
summary(xss)
or
map(print, sum(map(math.sqr, (x for x in xs))))
There is a function that returns a sum of integers from list x that are greater than integer y. If there is none of the numbers greater than y the function returns 0.
def sum_greater(x, y):
result = 0
for i in range(len(x)):
if x[i] > y:
result = result + x[i]
return result
My question: is it possible (and if it is than how) to make a list comprehension from this function?
You can use the sum() function with a generator expression:
sum(i for i in x if i > y)
Since 0 is the natural result of the sum of nothing, that doesn't need any special handling. You can send a generator expression to the built-in sum:
def sum_greater(x, y):
return sum(i for i in x if i>y)
I need help for this task. I have to write:
two assignment statements that respectively assigns to the variable SQUARE the lambda term that squares the argument , and assigns to the variable ODD the lambda term that tests if its argument is an odd number.
A python lambda function looks like the following:
double = lambda x: x*2
It is a quick way to write a one-line function and is just shorthand for:
def double(x):
return x*2
Google "python lambda" and you will find tutorials and more examples.
From what I understood I came up with the following code.Hope it helps
numbers = range(5) ## few range of numbers
for i in numbers:
square = lambda x: x*x ## returns the square of each value in numbers
print square(i) ## prints the square of each value in numbers
for j in numbers:
odd = lambda y: y%2 !=0 ## checks if odd or even
print odd(j) ## print True if divisible (meaning its even number) or False (meaning its odd)
I recently started learning Python, and the concept of for loops is still a little confusing for me. I understand that it generally follows the format for x in y, where y is just some list.
The for-each loop for (int n: someArray)
becomes for n in someArray,
And the for loop for (i = 0; i < 9; i-=2) can be represented by for i in range(0, 9, -2)
Suppose instead of a constant increment, I wanted i*=2, or even i*=i. Is this possible, or would I have to use a while loop instead?
As you say, a for loop iterates through the elements of a list. The list can contain anything you like, so you can construct a list beforehand that contains each step.
A for loop can also iterate over a "generator", which is a small piece of code instead of an actual list. In Python, range() is actually a generator (in Python 2.x though, range() returned a list while xrange() was the generator).
For example:
def doubler(x):
while True:
yield x
x *= 2
for i in doubler(1):
print i
The above for loop will print
1
2
4
8
and so on, until you press Ctrl+C.
You can use a generator expression to do this efficiently and with little excess code:
for i in (2**x for x in range(10)): #In Python 2.x, use `xrange()`.
...
Generator expressions work just like defining a manual generator (as in Greg Hewgill's answer), with a syntax similar to a list comprehension. They are evaluated lazily - meaning that they don't generate a list at the start of the operation, which can cause much better performance on large iterables.
So this generator works by waiting until it is asked for a value, then asking range(10) for a value, doubling that value, and passing it back to the for loop. It does this repeatedly until the range() generator yields no more values.
Bear in mind that the 'list' part of the Python can be any iterable sequence.
Examples:
A string:
for c in 'abcdefg':
# deal with the string on a character by character basis...
A file:
with open('somefile','r') as f:
for line in f:
# deal with the file line by line
A dictionary:
d={1:'one',2:'two',3:'three'}
for key, value in d.items():
# deal with the key:value pairs from a dict
A slice of a list:
l=range(100)
for e in l[10:20:2]:
# ever other element between 10 and 20 in l
etc etc etc etc
So it really is a lot deeper than 'just some list'
As others have stated, just set the iterable to be what you want it to be for your example questions:
for e in (i*i for i in range(10)):
# the squares of the sequence 0-9...
l=[1,5,10,15]
for i in (i*2 for i in l):
# the list l as a sequence * 2...
You will want to use list comprehensions for this
print [x**2 for x in xrange(10)] # X to the 2nd power.
and
print [x**x for x in xrange(10)] # X to the Xth power.
The list comprehension syntax is a follows:
[EXPRESSION for VARIABLE in ITERABLE if CONDITION]
Under the hood, it acts similar to the map and filter function:
def f(VARIABLE): return EXPRESSION
def c(VARIABLE): return CONDITION
filter(c, map(f, ITERABLE))
Example given:
def square(x): return x**2
print map(square, xrange(10))
and
def hypercube(x): return x**x
print map(hypercube, xrange(10))
Which can be used as alternative approach if you don't like list comprehensions.
You could as well use a for loop, but that would step away from being Python idiomatic...
Just for an alternative, how about generalizing the iterate/increment operation to a lambda function so you can do something like this:
for i in seq(1, 9, lambda x: x*2):
print i
...
1
2
4
8
Where seq is defined below:
#!/bin/python
from timeit import timeit
def seq(a, b, f):
x = a;
while x < b:
yield x
x = f(x)
def testSeq():
l = tuple(seq(1, 100000000, lambda x: x*2))
#print l
def testGen():
l = tuple((2**x for x in range(27)))
#print l
testSeq();
testGen();
print "seq", timeit('testSeq()', 'from __main__ import testSeq', number = 1000000)
print "gen", timeit('testGen()', 'from __main__ import testGen', number = 1000000)
The difference in performance isn't that much:
seq 7.98655080795
gen 6.19856786728
[EDIT]
To support reverse iteration and with a default argument...
def seq(a, b, f = None):
x = a;
if b > a:
if f == None:
f = lambda x: x+1
while x < b:
yield x
x = f(x)
else:
if f == None:
f = lambda x: x-1
while x > b:
yield x
x = f(x)
for i in seq(8, 0, lambda x: x/2):
print i
Note: This behaves differently to range/xrange in which the direction </> test is chosen by the iterator sign, rather than the difference between start and end values.