For Loop Parsing with % - python

Just started learning Python a month ago. I'm stumped on an issue.
Trying to update a dictionary using a for loop. I would like to store the variable using the for loop's variable name as key and the variable value as the dictionary's value. I'm trying to use % to make it a one liner. Here's what I have so far:
grbl_parser_d = {
'a': 'null', # Motion Mode
'b': 'null', # Coordinate System Select
'c': 'null' # Plane Select
}
grbl_out = [GC:G0 G54 G17]
def filtergrblparser():
global grbl_parser_d
for l, r in [grbl_out.strip('[]').split(':')]:
for a, b, c in [r.split(' ')]:
# grbl_parser_d.update({'%': x}) % x
grbl_parser_d.update({'a': a})
grbl_parser_d.update({'b': b})
grbl_parser_d.update({'c': c})
The 'grbl_out' variable is the output from an Arduino.
Trying to use something like: grbl_parser_d.update({'%': a}) % a.name
'a.name' would be the for loop's variable name, not the value. Is this even possible? Any other suggestions and tips to clean up the code would also be greatly appreciated. Thanks!

You don't need loops for this, and I wouldn't try to cram it onto one line. Here's a simple function that should do what you want.
def filtergrblparser(grbl_out):
l, r = grbl_out.strip('[]').split(':')
a, b, c = r.split(' ')
grbl_parser_d = {
'a': a, # Motion Mode
'b': b, # Coordinate System Select
'c': c # Plane Select
}
return grbl_parser_d
# I'm assuming you meant this to be a string
grbl_out = "[GC:G0 G54 G17]"
grbl_parser_d = filtergrblparser(grbl_out)
print(grbl_parser_d)
# {'a': 'G0', 'b': 'G54', 'c': 'G17'}

This is generally a bad idea, but it could be done with another for loop.
# it's not clear why you're throwing this in a list just to iterate once over it
l, r = grbl_out.strip('[]').split(':')
a, b, c = r.split(' ')
for k in ['a', 'b', 'c']:
grbl_parser_d[k] = vars()[k]
But really it looks like you're trying to do:
grbl_parser_d = dict(zip('abc', grbl_out.strip('[]').split(':')[1].split(' ')))
Which is probably best written as:
l, r = grbl_out.strip('[]').split(':')
grbl_parser_d = dict(zip('abc', r.split(' ')))

Related

I'm trying to make a dictionary whose name is defined by user input. How do I do this?

I ran into a problem when I tried to do something like this:
a=input()
b=input()
c=input()
a's user input = {'y': b, 'z': c}
Use a dictionary to store your dictionaries. That allows you to use the input as dictionary key:
mydicts = {}
a=input()
b=input()
c=input()
mydicts[a] = {'y': b, 'z': c}
Then later you can retrieve in the same way using mydicts[]. This will print the value of b when some_var matches a:
print(mydicts[some_var]['y'])
I guess it should be sth like this:
d = {}
u_key = ''
while (u_key != 'END'):
u_key = input('Enter key:\n')
d[u_key] = input(f'Enter value for {u_key}\n')
print(d)

Python: Using dictionary to print dependent variables

I am given a question as follows:
B = C, D
A = B
C = E
meaning B is dependent on variable C and D, while A is dependent on B, and so on. Variable E and D is independent.
Input of 'A' should then return:
E, C, D, B, A
listing all dependent variables. To solve this problem, I first started off by defining a dictionary to iterate this condition easily:
letter = {'A' : ['B'], 'B' : ['C', 'D'], 'C' : ['E']}
However, I am now stuck on how I should loop this in order to print all the children efficiently. I believe this is wrong but I think I may be going in the right direction:
def problem(value):
letter = {'A' : ['B'], 'B' : ['C', 'D'], 'C' : ['E']}
for i in letter:
if i != value:
continue
if len(letter[i]) > 1:
for k in letter:
print("".join(letter[k]), k)
print("".join(letter[i]), i)
Please help!
Stolen from http://code.activestate.com/recipes/576570-dependency-resolver/ after some quick googling.
def dep(arg):
'''
Dependency resolver
"arg" is a dependency dictionary in which
the values are the dependencies of their respective keys.
'''
d=dict((k, set(arg[k])) for k in arg)
r=[]
while d:
# values not in keys (items without dep)
t=set(i for v in d.values() for i in v)-set(d.keys())
# and keys without value (items without dep)
t.update(k for k, v in d.items() if not v)
# can be done right away
r.append(t)
# and cleaned up
d=dict(((k, v-t) for k, v in d.items() if v))
return r
if __name__=='__main__':
d=dict(
a=('b','c'),
b=('c','d'),
e=(),
f=('c','e'),
g=('h','f'),
i=('f',)
)
print dep(d)
You have a list inside of another list. Write a nested for loop inside of another for loop and then run that through your test logic. For the outer list iterate over every part of the inner list and then move to the next part of the outer list.

Find the minimum and display the variable name in python

You have got three variables like
a = 1
b = 2
c = 3
and you find the minimum can you somehow display the variable name instead of the value it has
Example
d = min[a,b,c]
after this operation d should become c since c is the greatest. Or maybe there's some alternative way because i want to assign the variable name in another operation afterwards.
Put variables into a dictionary and call min() with specifying dictionary get as a key:
>>> a = 1
>>> b = 2
>>> c = 3
>>> data = {'a': a, 'b': b, 'c': c}
>>> min(data, key=data.get)
'a'
You shouldn't do that. Instead, you should do something like:
data = {
'a' : 1
'b' : 2
'c' : 3
}
# get the minimum item, by the value.
smallest = min(data.items(), key = lambda item: item[1])
data[smallest] = my_new_value

mapping in SD in python

Hi I want to map the sd keys and values from the result of two different query. to make it more clear i have written code.
rv = plpy.execute(select id from ABC);
if this returns 1, 2, 3
rv = plpy.execute(select name from XYZ);
if this returns A,B,C
Now I need a way where I can map these two ids, so that id retrieved from first query can be used as key and name retrieved from second query can be used as values, so i will have something like
SD[1] = A
SD[2] = B
SD[3] = C
THis is needed as I am trying to create dynamic SD for my application.
Can somebody suggest me some solution.
I'm unfamiliar with plpy, so maybe I'm totally off. But if what you want to do is to create a python dictionary with key:value-pairs based on results from two queries this is my suggestion:
If these are your queries:
a = [a, b, c]
b = [1, 2, 3]
Then:
dict(zip(a, b))
Gives you a dictionary like this:
{'a': '1', 'b': '2', 'c': '3'}

Destructuring-bind dictionary contents

I am trying to 'destructure' a dictionary and associate values with variables names after its keys. Something like
params = {'a':1,'b':2}
a,b = params.values()
But since dictionaries are not ordered, there is no guarantee that params.values() will return values in the order of (a, b). Is there a nice way to do this?
from operator import itemgetter
params = {'a': 1, 'b': 2}
a, b = itemgetter('a', 'b')(params)
Instead of elaborate lambda functions or dictionary comprehension, may as well use a built in library.
One way to do this with less repetition than Jochen's suggestion is with a helper function. This gives the flexibility to list your variable names in any order and only destructure a subset of what is in the dict:
pluck = lambda dict, *args: (dict[arg] for arg in args)
things = {'blah': 'bleh', 'foo': 'bar'}
foo, blah = pluck(things, 'foo', 'blah')
Also, instead of joaquin's OrderedDict you could sort the keys and get the values. The only catches are you need to specify your variable names in alphabetical order and destructure everything in the dict:
sorted_vals = lambda dict: (t[1] for t in sorted(dict.items()))
things = {'foo': 'bar', 'blah': 'bleh'}
blah, foo = sorted_vals(things)
How come nobody posted the simplest approach?
params = {'a':1,'b':2}
a, b = params['a'], params['b']
Python is only able to "destructure" sequences, not dictionaries. So, to write what you want, you will have to map the needed entries to a proper sequence. As of myself, the closest match I could find is the (not very sexy):
a,b = [d[k] for k in ('a','b')]
This works with generators too:
a,b = (d[k] for k in ('a','b'))
Here is a full example:
>>> d = dict(a=1,b=2,c=3)
>>> d
{'a': 1, 'c': 3, 'b': 2}
>>> a, b = [d[k] for k in ('a','b')]
>>> a
1
>>> b
2
>>> a, b = (d[k] for k in ('a','b'))
>>> a
1
>>> b
2
Here's another way to do it similarly to how a destructuring assignment works in JS:
params = {'b': 2, 'a': 1}
a, b, rest = (lambda a, b, **rest: (a, b, rest))(**params)
What we did was to unpack the params dictionary into key values (using **) (like in Jochen's answer), then we've taken those values in the lambda signature and assigned them according to the key name - and here's a bonus - we also get a dictionary of whatever is not in the lambda's signature so if you had:
params = {'b': 2, 'a': 1, 'c': 3}
a, b, rest = (lambda a, b, **rest: (a, b, rest))(**params)
After the lambda has been applied, the rest variable will now contain:
{'c': 3}
Useful for omitting unneeded keys from a dictionary.
Hope this helps.
Maybe you really want to do something like this?
def some_func(a, b):
print a,b
params = {'a':1,'b':2}
some_func(**params) # equiv to some_func(a=1, b=2)
If you are afraid of the issues involved in the use of the locals dictionary and you prefer to follow your original strategy, Ordered Dictionaries from python 2.7 and 3.1 collections.OrderedDicts allows you to recover you dictionary items in the order in which they were first inserted
(Ab)using the import system
The from ... import statement lets us desctructure and bind attribute names of an object. Of course, it only works for objects in the sys.modules dictionary, so one could use a hack like this:
import sys, types
mydict = {'a':1,'b':2}
sys.modules["mydict"] = types.SimpleNamespace(**mydict)
from mydict import a, b
A somewhat more serious hack would be to write a context manager to load and unload the module:
with obj_as_module(mydict, "mydict_module"):
from mydict_module import a, b
By pointing the __getattr__ method of the module directly to the __getitem__ method of the dict, the context manager can also avoid using SimpleNamespace(**mydict).
See this answer for an implementation and some extensions of the idea.
One can also temporarily replace the entire sys.modules dict with the dict of interest, and do import a, b without from.
Warning 1: as stated in the docs, this is not guaranteed to work on all Python implementations:
CPython implementation detail: This function relies on Python stack frame support
in the interpreter, which isn’t guaranteed to exist in all implementations
of Python. If running in an implementation without Python stack frame support
this function returns None.
Warning 2: this function does make the code shorter, but it probably contradicts the Python philosophy of being as explicit as you can. Moreover, it doesn't address the issues pointed out by John Christopher Jones in the comments, although you could make a similar function that works with attributes instead of keys. This is just a demonstration that you can do that if you really want to!
def destructure(dict_):
if not isinstance(dict_, dict):
raise TypeError(f"{dict_} is not a dict")
# the parent frame will contain the information about
# the current line
parent_frame = inspect.currentframe().f_back
# so we extract that line (by default the code context
# only contains the current line)
(line,) = inspect.getframeinfo(parent_frame).code_context
# "hello, key = destructure(my_dict)"
# -> ("hello, key ", "=", " destructure(my_dict)")
lvalues, _equals, _rvalue = line.strip().partition("=")
# -> ["hello", "key"]
keys = [s.strip() for s in lvalues.split(",") if s.strip()]
if missing := [key for key in keys if key not in dict_]:
raise KeyError(*missing)
for key in keys:
yield dict_[key]
In [5]: my_dict = {"hello": "world", "123": "456", "key": "value"}
In [6]: hello, key = destructure(my_dict)
In [7]: hello
Out[7]: 'world'
In [8]: key
Out[8]: 'value'
This solution allows you to pick some of the keys, not all, like in JavaScript. It's also safe for user-provided dictionaries
With Python 3.10, you can do:
d = {"a": 1, "b": 2}
match d:
case {"a": a, "b": b}:
print(f"A is {a} and b is {b}")
but it adds two extra levels of indentation, and you still have to repeat the key names.
Look for other answers as this won't cater to the unexpected order in the dictionary. will update this with a correct version sometime soon.
try this
data = {'a':'Apple', 'b':'Banana','c':'Carrot'}
keys = data.keys()
a,b,c = [data[k] for k in keys]
result:
a == 'Apple'
b == 'Banana'
c == 'Carrot'
Well, if you want these in a class you can always do this:
class AttributeDict(dict):
def __init__(self, *args, **kwargs):
super(AttributeDict, self).__init__(*args, **kwargs)
self.__dict__.update(self)
d = AttributeDict(a=1, b=2)
Based on #ShawnFumo answer I came up with this:
def destruct(dict): return (t[1] for t in sorted(dict.items()))
d = {'b': 'Banana', 'c': 'Carrot', 'a': 'Apple' }
a, b, c = destruct(d)
(Notice the order of items in dict)
An old topic, but I found this to be a useful method:
data = {'a':'Apple', 'b':'Banana','c':'Carrot'}
for key in data.keys():
locals()[key] = data[key]
This method loops over every key in your dictionary and sets a variable to that name and then assigns the value from the associated key to this new variable.
Testing:
print(a)
print(b)
print(c)
Output
Apple
Banana
Carrot
An easy and simple way to destruct dict in python:
params = {"a": 1, "b": 2}
a, b = [params[key] for key in ("a", "b")]
print(a, b)
# Output:
# 1 2
I don't know whether it's good style, but
locals().update(params)
will do the trick. You then have a, b and whatever was in your params dict available as corresponding local variables.
Since dictionaries are guaranteed to keep their insertion order in Python >= 3.7, that means that it's complete safe and idiomatic to just do this nowadays:
params = {'a': 1, 'b': 2}
a, b = params.values()
print(a)
print(b)
Output:
1
2

Categories

Resources