Transform normal python function to lambda - python

i have this function:
def add_transaction(list_of_items):
for item in list_of_items:
if item not in item_dict.keys():
raise ValueError("You cannot make a transaction containing items that are not present in the items dictionary because it means that the Store does not has those items available, please add the items to the items dictionary first")
transaction_data.append(list_of_items)
return list_of_items
Do you know how it is possible to transform that into a lambda function?
Thanks in advance
Tried to create the lambda function for this function but not sure of how to make it work.

You can do this with set.isssubset() and this hack to raise an exception from a lambda. You'll also need to abuse the or operator to both call transaction_data.append(lst) and return the list.
item_dict = {'a': 1, 'b': 2, 'c': 3}
transaction_data = []
fn = lambda lst: (transaction_data.append(lst) or lst) if set(lst).issubset(item_dict.keys()) else exec("raise ValueError('not in store')")
print(fn(['a', 'c'])) # => ['a', 'c']
print(transaction_data) # => ['a', 'c']

Related

creating a dictionary using two lists (no zip) PYTHON

I am trying to create a dictionary using two lists without the use of zip. can someone help me to finish the code. The function should return an empty dictionary if the lists were empty.
key_list=[1,2,3,4]
value_list=['a','b','c','d']
def list_to_dict(key_list,value_list):
new_dict={}
if len(key_list)!=0 and len(value_list)!=0:
for i in range(len(key_list)):
dict[key_list[i]]=value_list[i]
return new_dict
the output I want is
new_dict={1:'a', 2:'b', 3:'c', 4:'d'}
Your return should go outside the for loop scope, also check for the min lenght of both lists:
def list_to_dict(key_list,value_list):
new_dict = {}
if len(key_list) != 0 and len(value_list) != 0:
for i in range(min(len(key_list), len(value_list))):
new_dict[key_list[i]] = value_list[i]
return new_dict
key_list=[1,2,3,4]
value_list=['a','b','c','d']
def list_to_dict(key_list,value_list):
new_dict={}
if len(key_list)!=0 and len(value_list)!=0 and len(key_list) == len(value_list):
for key, index in enumerate(key_list):
dict[key]=value_list[index]
return new_dict
You had an error in your indentation. Also, both lists need to be the same length to avoid an error, so I added that check. For extra learning, look up enumerate. GL on the rest of your homework :)
Try this.
key_list=[1,2,3,4]
value_list=['a','b','c','d']
def list_to_dict(key_list,value_list):
new_dict={}
if len(key_list)!=0 and len(value_list)!=0:
for i in range(len(key_list)):
new_dict[key_list[i]]=value_list[i]
return new_dict
key_list=[1,2,3,4]
value_list=['a','b','c','d']
def list_to_dict(key_list,value_list):
"""using dict comprehension, creating new key-value pair
for each key present in key list againt the value present in the value list."""
new_dict={key_list[i]:value_list[i] for i in range(len(key_list))}
return new_dict
result = list_to_dict(key_list,value_list)
print(result)
output
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}
You can use a dict comprehension:
key_list = [1, 2, 3, 4]
value_list=['a', 'b', 'c', 'd']
def list_to_dict(key_list, value_list):
assert len(key_list) == len(value_list), "Both input lists should have equal length"
return {key_list[i]: value_list[i] for i in range(len(key_list))}
key_list = [1, 2, 3, 4]
value_list=['a', 'b', 'c', 'd']
my_dict={}
def list_dict(key_list,value_list):
for i in range((len(key_list))-1):
my_dict[key_list[i]] = value_list[i] #using loop to add one by one
i=i+1
return my_dict
You can try this for your home work
list_dict(key_list,value_list)

Is there a python function like Clojure's get-in?

Is there something equivalent to Clojure's get-in function in Python? It gets the data at the given path in some data structure.
In Clojure it is used like:
(def employee
{:name "John"
:details {:email "info#domain.com"
:phone "555-144-300"}})
(get-in employee [:details :email]) ; => "info#domain.com"
If translated to Python syntax it would be used like:
dictionary = {'a': {'b': 10}}
get_in(dictionary, ['a', 'b']) # => 10
This function is used to access arbitrary data points in nestled data structures where the paths are not known at compile time, they are dynamic. More usage examples of get-in can be found on clojuredocs.
No, but you can certainly make one
def get_in(d, keys):
if not keys:
return d
return get_in(d[keys[0]], keys[1:])
You can write:
dictionary.get('details', {}).get('email')
This will safely get the value you need or None, without throwing an exception - just like Clojure's get-in does.
If you need a dedicated function for that, you can write:
def get_in(d, keys):
if not keys:
return d
elif len(keys) == 1:
return d.get(keys[0])
else:
return get_in(d.get(keys[0], {}), keys[1:])
A simple for loop should solve your problem -
x = {'a':{'b':{'c': 1}}}
def get_element(elements, dictionary):
for i in elements:
try:
dictionary = dictionary[i]
except KeyError:
return False
return dictionary
print(get_element(['a', 'b', 'c'], x))
# 1
print(get_element(['a', 'z', 'c'], x))
# False

Function to create dictionary with default values that can be either immutable or mutable

I have a function to create a dictionary with specific keys, which accepts a parameter to specify what each key's "default" value should be.
def new_dict(entrys_default=0):
my_dict = {}
for k in ['a', 'b', 'c']:
my_dict[k] = entrys_default
return my_dict
The issue is that when I call it with new_dict(entrys_default=[]) so that each entry in the dictionary is created with a new empty list as its value, when I then update one entry with returned_dict['a'].append(123) then all entries are updated:
{'a': [123], 'b': [123], 'c': [123]}
This doesn't happen when using an integer, and I understand that it is because the entrys_default is immutable when it is an integer, but is a reference to the same list when it is a list or dictionary.
I want to be able to have this function work the same as it does for integer parameters with lists and dictionaries as entrys_default - i.e. each entry has its own list/dictionary - but want to keep the function flexible to also work for integers.
Can anyone please suggest the best way to go about this?
Do what collections.defaultdict does; instead of taking an "example" default value, take a function that returns the desired default value. Then call that function and use its return value to initialize each element of the dict being constructed.
def new_dict(make_default=int): # int() == 0
my_dict = {}
for k in ['a', 'b', 'c']:
my_dict[k] = make_default()
return my_dict
d = new_dict(list) # list() == [], but a distinct list each time it is called
d['a'].append(123)
assert d['a'] != d['b']

Python: Creating a dictionary using list comprehension from a list using lambda

Conceptually, here is what I want to do:
lookup = {'A': 'aaa', 'B': 'bbb', 'C': 'ccc'}
keys = ['A', 'B', 'Z'] # Note 'Z' does not exist in dict
result = {}
for key in keys:
if key in lookup:
result[key] = lookup[key]
else:
result[key] = None
The above code yields the following, i.e.
# result == {'A': 'aaa', 'Z': None, 'B': 'bbb'}
Based on the advise in this post about dictionary comprehension syntax I am able to do the following using v2.6 syntax:
result = dict((lambda x: (x, lookup[x]) if x in lookup else (x, None))(key) for key in keys)
Which works and produces same results.
However, I was hoping that I would be able to do the following in v2.7 style (also mentioned in the above post). But that does not seem to work,
result = { (lambda x: x: a_dict[x] if x in a_dict else x: None)(key) for key in a_list }
I seem to be running afoul of use of : in lambda with that in denoting a key. I have also reviewed the examples given in the original PEP, too. They don't provide any guidance, either. Below is the output from command line:
>>> result = { (lambda x: x : a_dict[x] if x in a_dict else x: None)(key) for key in a_list }
File "<stdin>", line 1
result = { (lambda x: x : a_dict[x] if x in a_dict else x: None)(key) for key in a_list }
^
SyntaxError: invalid syntax
What am I doing wrong? Is it possible to do what I am trying to do, i.e. use v2.7 syntax of dictionary comprehension with lambda?
Please note that I ask this only out of curiosity; it's not that I have a compulsion to write such production code, one that would require an expert to understand!
PS: I should mention two other related posts that I found helpful while trying do this. First is about using lambda in list comprehension. And another is creating a dictionary using list.
To do what you are trying with dictionary comprehension, you should make use of dict.get() method. Example -
>>> lookup = {'A': 'aaa', 'B': 'bbb', 'C': 'ccc'}
>>> keys = ['A', 'B', 'Z']
>>> result = {key:lookup.get(key) for key in keys}
>>> result
{'Z': None, 'A': 'aaa', 'B': 'bbb'}
dict.get() returns None if the key is not present in the dictionary. You can also specify a second argument to dict.get() which would be the default value returned, if the key you are trying to get is not present in the dictionary.
To answer the question, you cannot use lambda to return something like a key:value pair in a dictionary comprehension (since the : syntax is not valid). If you want to do that, you should use dict() function with a generator expression , Example -
result = dict((lambda x: (x,a_dict[x]) if x in a_dict else (x,None))(key) for key in a_list)
or the more readable map() version -
result = dict(map((lambda x: (x,a_dict[x]) if x in a_dict else (x,None)), a_list)
What you are trying to do can be done with a simple dictionary comprehension:
result = {k: lookup.get(k) for k in keys}
k will be the key and lookup.get(k) will be the value. .get() will get the value of a key from a dictionary or None if it is not present. The default value can also be set as the 2nd argument.

Is it possible to turn a list into a nested dict of keys *without* recursion?

Supposing I had a list as follows:
mylist = ['a','b','c','d']
Is it possible to create, from this list, the following dict without using recursion/a recursive function?
{
'a': {
'b': {
'c': {
'd': { }
}
}
}
}
For the simple case, simply iterate and build, either from the end or the start:
result = {}
for name in reversed(mylist):
result = {name: result}
or
result = current = {}
for name in mylist:
current[name] = {}
current = current[name]
The first solution can also be expressed as a one-liner using reduce():
reduce(lambda res, name: {name: res}, reversed(mylist), {})
For this simple case at least, yes:
my_list = ['a', 'b', 'c', 'd']
cursor = built_dict = {}
for value in my_list:
cursor[value] = {}
cursor = cursor[value]
Or for fancyness and reduced readability:
dict = reduce(lambda x, y: {y: x}, reversed(myList), {})
It's worth mentioning that every recursion can be converted into iteration, although sometimes that might not be so easy. For the particular example in the question, it is simple enough, it's just a matter of accumulating the expected result in a variable and traversing the input list in the appropriate order. This is what I mean:
def convert(lst):
acc = {}
for e in reversed(lst):
acc = {e: acc}
return acc
Or even shorter, the above algorithm can be expressed as a one-liner (assuming Python 2.x, in Python 3.x reduce was moved to the functools module). Notice how the variable names in the previous solution correspond to the lambda's parameters, and how in both cases the initial value of the accumulator is {}:
def convert(lst):
return reduce(lambda acc, e: {e: acc}, reversed(lst), {})
Either way, the function convert works as expected:
mylist = ['a','b','c','d']
convert(mylist)
=> {'a': {'b': {'c': {'d': {}}}}}
mydict = dict()
currentDict = mydict
for el in mylist:
currentDict[el] = dict()
currentDict = currentDict[el]

Categories

Resources