I am a python newbie trying to achieve the following:
I have a list of lists:
lst = [[567,345,234],[253,465,756, 2345],[333,777,111, 555]]
This is exactly what the bind
function in a Monad is used for.
With the bind
function you can combine multiple lambda's into one lambda, each lambda representing a statement.
Or if you want to avoid lambda and have a generator instead of a list:
(sorted(col)[1] for col in lst)
Let me present to you a glorious but terrifying hack:
import types
def _obj():
return lambda: None
def LET(bindings, body, env=None):
'''Introduce local bindings.
ex: LET(('a', 1,
'b', 2),
lambda o: [o.a, o.b])
gives: [1, 2]
Bindings down the chain can depend on
the ones above them through a lambda.
ex: LET(('a', 1,
'b', lambda o: o.a + 1),
lambda o: o.b)
gives: 2
'''
if len(bindings) == 0:
return body(env)
env = env or _obj()
k, v = bindings[:2]
if isinstance(v, types.FunctionType):
v = v(env)
setattr(env, k, v)
return LET(bindings[2:], body, env)
You can now use this LET
form as such:
map(lambda x: LET(('_', x.sort()),
lambda _: x[1]),
lst)
which gives: [345, 465, 333]
to demonstrate the lambda x:[f1(),f2()]
effect which enables us to execute multiple functions in lambda
. it also demonstrates the single line if else conditions if you really want to shrink the code.
lambda x:[exec('a=[1]'),exec('b=2')]
a python implementation of touch(linux) command which creates empty files if they are not already existing.
def touch(fpath):
check= os.path.exists(fpath)
(lambda fname1:[open(fname1,"w+",errors="ignore").write(""),print('Touched',fname1)]
if not check else None) (fpath)
will print [ Touched fpath
] where fpath
is file path given as input. will do nothing if file already exist.
the (lambda x: [ f(x), f2(x) ] ) (inp)
<- we pass the 'inp
' as input to lambda
which in this case is the fpath
.
You can do it in O(n) time using min and index instead of using sort or heapq.
First create new list of everything except the min value of the original list:
new_list = lst[:lst.index(min(lst))] + lst[lst.index(min(lst))+1:]
Then take the min value of the new list:
second_smallest = min(new_list)
Now all together in a single lambda:
map(lambda x: min(x[:x.index(min(x))] + x[x.index(min(x))+1:]), lst)
Yes it is really ugly, but it should be algorithmically cheap. Also since some folks in this thread want to see list comprehensions:
[min(x[:x.index(min(x))] + x[x.index(min(x))+1:]) for x in lst]
I'll give you another solution, Make your lambda invoke a function.
def multiple_statements(x, y):
print('hi')
print('there')
print(x)
print(y)
return 1
junky = lambda x, y: multiple_statements(x, y)
junky('a', 'b');