Dictionary Operations... Index / Iterate / Validate - python

I'd like to:
Check a key / value at position i
Check to see if key / value contains a string
delete / store in another variable either the key / value
The equivelant of this Java code:
//Some list...
ArrayList<String> example;
...
//Index into data structure
example.get(i);
//Check for some string...
if (example.get(i).contains("someText")){
somestuff;
}
//Store in some other variable
exam = example.get(i)
That's what I'm effectively trying to in Java, however I'd like to be able to do that with Python dictionarties however I'm not sure if this is possible, as I find the Python documentation rather hard to read.

Python dictionaries are implemented as hash tables, so there is no intrinsic ordering; therefore, "position i" is a totally nonsensical concept for a dict -- it's like asking for the dict entry that's most yellow, or that least resembles a llama... those concepts just don't apply to dict entries, and "position i" is just as totally inapplicable.
Where does that i come from, i.e., what's the real issue you're trying to solve? If your requirement is to iterate over the dictionary, you do that directly, without the crutch of a "numeric index". Or, if you do need to keep some specific order or other, then you don't use a dict, but rather some different data structure. If you explain exactly the purpose you're trying to address, I'm sure we can help you.

Direct translation (for an ArrayList<String>, you do not want a dictionary, you want a list):
example = ["foo", "bar", "baz"]
str = example[i]
if "someText" in str:
somestuff()
Get used to the for keyword, though, it's awesome in Python:
for str in example:
if "someText" in str:
someStuff()
Here's an example using dictionaries:
fruits = {
"apple": "red",
"orange": "orange",
"banana": "yellow",
"pear": "green"
}
for key in fruits:
if fruits[key] == "apple":
print "An apple is my favorite fruit, and it is", fruits[key]
else:
print "A", key, "is not my favorite fruit, and it is", fruits[key]
Iteration using for on a dictionary results in the keys, it's still up to you to index the item itself. As Alex pointed out, we're really off-base answering you with so little information, and it sounds like you're not well-rooted in data structures (dictionaries will probably yield a different order every time you iterate it).

Yo can do that to reproduce the same behavior that your example in Java.
# Some list
example = {} # or example = dict()
...
# Index into data estructure.
example[example.keys(i)]
# Check for some string...
if example[example.keys(i)] == 'someText' :
pass
# Store in some other variable...
exam = example[example.keys(i)]
del example[example.keys(i)]
# ...or
exam = example.pop(example.keys(i))

What's nice about Python is that you can try code interactively.
So we create a list which is like a Java List:
>>> mylist = ["python","java","ruby"]
>>> mylist
['python', 'java', 'ruby']
We can get an entry in the list via its index:
>>> mylist[0]
'python'
And use the find function to search for substrings:
>>> mylist[1].find("av")
1
>>> mylist[1].find("ub")
-1
It returns -1 if the string isn't found.
Copying an entry to a new variable is done just how you'd expect:
>>> newvalue = mylist[2]
>>> newvalue
'ruby'
Or we can create a dict which is like a Java Map, storing by key rather than index, but these work very similarly to lists in Python:
>>> mydict = { 'python':'Guido', 'java':'James', 'ruby':'Yukihiro' }
>>> mydict['java']
'James'
>>> othervalue = mydict['ruby']
>>> othervalue
'Yukihiro'
>>> mydict['python'].find('uid')
1
>>> mydict['python'].find('hiro')
-1
>>> mydict['ruby'].find('hiro')
4

Related

Python set dictionary nested key with dot delineated string

If I have a dictionary that is nested, and I pass in a string like "key1.key2.key3" which would translate to:
myDict["key1"]["key2"]["key3"]
What would be an elegant way to be able to have a method where I could pass on that string and it would translate to that key assignment? Something like
myDict.set_nested('key1.key2.key3', someValue)
Using only builtin stuff:
def set(my_dict, key_string, value):
"""Given `foo`, 'key1.key2.key3', 'something', set foo['key1']['key2']['key3'] = 'something'"""
# Start off pointing at the original dictionary that was passed in.
here = my_dict
# Turn the string of key names into a list of strings.
keys = key_string.split(".")
# For every key *before* the last one, we concentrate on navigating through the dictionary.
for key in keys[:-1]:
# Try to find here[key]. If it doesn't exist, create it with an empty dictionary. Then,
# update our `here` pointer to refer to the thing we just found (or created).
here = here.setdefault(key, {})
# Finally, set the final key to the given value
here[keys[-1]] = value
myDict = {}
set(myDict, "key1.key2.key3", "some_value")
assert myDict == {"key1": {"key2": {"key3": "some_value"}}}
This traverses myDict one key at a time, ensuring that each sub-key refers to a nested dictionary.
You could also solve this recursively, but then you risk RecursionError exceptions without any real benefit.
There are a number of existing modules that will already do this, or something very much like it. For example, the jmespath module will resolve jmespath expressions, so given:
>>> mydict={'key1': {'key2': {'key3': 'value'}}}
You can run:
>>> import jmespath
>>> jmespath.search('key1.key2.key3', mydict)
'value'
The jsonpointer module does something similar, although it likes / for a separator instead of ..
Given the number of pre-existing modules I would avoid trying to write your own code to do this.
EDIT: OP's clarification makes it clear that this answer isn't what he's looking for. I'm leaving it up here for people who find it by title.
I implemented a class that did this a while back... it should serve your purposes.
I achieved this by overriding the default getattr/setattr functions for an object.
Check it out! AndroxxTraxxon/cfgutils
This lets you do some code like the following...
from cfgutils import obj
a = obj({
"b": 123,
"c": "apple",
"d": {
"e": "nested dictionary value"
}
})
print(a.d.e)
>>> nested dictionary value

Python 3 how to get value from dictionary containing only one key-value pair with unknown key?

Hello Stack Overflow,
What is the most readable + simplest way to get a value from a dictionary that only contains one key-value pair?
Note: I do not know what the key is when I try to fetch the value, it's autogenerated.
Let's imagine the dictionary to look something like this:
my_dict = {
"unknown_key_name": 1
}
FYI I am using Python 3.6. My current solution is this: val = list(my_dict.values())[0]
I just have a feeling there is a more "elegant" solution, does anyone know of one?
Get the iterator for values then use the next call to get the first value:
my_dict = {
"unknown_key_name": 1
}
first_val = next(iter(my_dict.values()))
print(first_val) # 1
This won't put a list into memory just to get the first element.
Use name, value = my_dict.popitem()
>>> my_dict = {"unknown_key_name": 1}
>>> name, value = my_dict.popitem()
>>> name
'unknown_key_name'
>>> value
1
>>>

Change json.dumps dictionary values in python

So i have following dict:
my_dict{'key1': 'value1',
'key2': 'value2',
'key3': json.dumps([
{"**subkey1**": "subvalue1", "**subkey2**": "subvalue2",},
{"**subkey1**": "other_subvalue", "**subkey2**":"other_subvalue2"}])
}
What I need is to somehow made a def where i have to check and for each subkey2 to change its value only for the def itself
And all subkey1 to check if its value is the same like the second subkey1
Please note I am talking about only subkey1 which I have twice.
I don't want to set them manually. Mean I have this dict global, and calling it from many def, so i need to make these changes and check inside each def
What I tried is:
def recurse_keys(my_dict, indent = ''):
print(indent+str(key))
if isinstance(my_dict[key], dict):
recurse_keys(my_dict[key], indent+' ')
recurse_keys(my_dict)
And for now it is only printing all of my params, but am not sure how to proceed
Example:
my_dict{'name': 'georgi',
'famili': 'ivanov',
'drinks': json.dumps([
{"breakfast": "milk", "lunch": "beer",},
{"breakfast": "tea", "lunch":"vodka"}])
def test()
....check if both breakfast are the same and if not make them so....(all these, mean dict and the function it self are in same file)
so I need to check if the values for the two breakfast are the same (without to know them) and if they are not, to make them so.
And also to check if there is lunch with empty value or 0 and again if not, to make it so
If you want to edit a json string, then probably the easiest way is to decode it to python data types d = json.loads(str), edit it, then encode it back to string str = json.dumps(d) (python JSON).
import json
my_dict = {'name': 'georgi',\
'famili': 'ivanov',\
'drinks': json.dumps([\
{"breakfast": "milk", "lunch": "beer",},\
{"breakfast": "tea", "lunch":"vodka"}])};
ddict = json.loads(my_dict["drinks"]) # json str to python data types
seen = {}; # store the items already seen
# for each dictionary object in key3
for d in range(0,len(ddict)):
for k in ddict[d]:
if k in seen:
# update the value to the one already seen
ddict[d][k] = seen[k];
if k == "lunch" and (ddict[d] == "" or ddict[d] is None):
ddict[d] = alternative_lunch_value;
else:
seen[k] = ddict[d][k];
my_dict["drinks"] = json.dumps(ddict);
print(my_dict);
The result on my machine is:
{'drinks': '[{"breakfast": "milk", "lunch": "beer"}, {"breakfast": "milk", "lunch": "beer"}]',
'famili': 'ivanov',
'name': 'georgi'}
Updating dict values
Because you wanted to update the values in my_dict so that it can be read by other modules, rather than just read the values. If all you wanted to do was read the values, then you can iterate over the list ddict as follows:
for value in ddict:
print("Sub1:{0} Sub2:{1}\n".format(value["**subkey1**"], value["**subkey2**"]));
However, since you want to update the values in the existing list, then you will need to iterate over a list of the indexes. As shown below...
Range() and len()
Range(start,end) gives a list with values from start to end. So a = range(1,4) assigns [1,2,3,4] to a. Also len(a) will return the number of items in the list, so 4 in this case. Using these principals, you can iterate through your ddict.
for d in range(1,len(ddict):
ddict[d]["**subkey1**"] = new_value;
Hope this helps get you started. If you update your question with more details on exactly what you want (i.e. example input and output, perhaps psudo code), then we will be able to give you a better answer.

Breaking down list of list into dictionaries

I have a list of list, s, that is the result of querying a database on Fruit, item[0] is the name of the fruit, item[1] is the whether or not the fruit has seeds, and item[2] is whether or not it's edible.
s = [['Apple','Yes','Edible'], ['Watermellon','Yes','Yes']]
As my actual list is much bigger, I would like a really easy way to reference/return these values. For example, print my_dict['Apple']['Seeds'] would yield Yes
I think my best option would be to create a dictionary, but am looking for recommendations on if this is a good method and how to do this.
I started writing some code but am not sure how to get the second set of headers in place, so my example uses an index instead.
my_dict = {t[0]:t[1:] for t in s}
print my_dict['Apple'][0]
fruit_map = {
fruit: {'Seeds': seeds, 'Edible': edible} for fruit, seeds, edible in s}
If the second set of keys never changes, it would be better to define a proper object with fields. This might seem overkill or to verbose, but there is always collections.namedtuple to help.
namedtuple creates a new class from a list of field names. That class also supports being initialized by a list. To use your example:
import collections
Fruit = collections.namedtuple('Fruit', ['name', 'seeds', 'edible'])
This way, you can easily create Fruit objects from a list:
f = Fruit('Apple', True, False)
# Or, if you already have a list with the values
params = ['Apple', True, False]
f = Fruit(*params)
print f.seed
So you can create a list of fruits in a very easy way:
s = [['Apple','Yes','Edible'], ['Watermellon','Yes','Yes']]
fruits = [Fruit(*l) for l in s]
You really need to have a dictionary indexed by a certain field, it is not much different:
s = [['Apple','Yes','Edible'], ['Watermellon','Yes','Yes']]
fruit_dict = {l[0]: Fruit(*l) for l in s}
print(fruit_dict['Apple'].seeds)
namedtuples can be very convenient when transforming lists of values into more easy to use objects (such as when reading a CSV file, which is a case very similar to what you are asking).
import copy
def list_to_dict(lst):
local = copy.copy(lst) # copied lst to local
fruit = [i.pop(0) for i in local] # get fruit names
result = {}
for i in range(len(local)):
result[fruit[i]] = local[i]
return result
This returns the dictionary you want.

create seperate instances in each element in list/dict comprehension in Python

My codes are like this:
widgets = {x: Select2Widget(attrs={"style": "width: 300px;"}) for x in
['paper', 'factor', 'cell_line', 'cell_type']}
This will cause error because all the values of the dict of widgets will share the same instance. To avoid this issue, I'll have to write the codes like the following:
widgets = {
'paper': Select2Widget(attrs={"style" : "width: 300px;"}),
'factor': Select2Widget(attrs={"style" : "width: 300px;"}),
'cell_line': Select2Widget(attrs={"style" : "width: 300px;"}),
'cell_type': Select2Widget(attrs={"style" : "width: 300px;"}),}
I was wondering whether this is a way to write concise codes while assigning different instance for the value of each element in the dictionary. Does anyone have ideas about this?
No, using a dict comprehension creates separate instances.
That is the point of a dict comprehension; the left-hand side expressions for key and value are evaluated each iteration.
Demo:
>>> demo = {i: [] for i in range(3)}
>>> demo[0] is demo[1]
False
Here separate lists are created. If you were to use, say, dict.fromkeys() then you would be sharing the same value:
>>> demo = dict.fromkeys(range(3), [])
>>> demo[0] is demo[1]
True
Because your dict comprehension uses a literal dict expression for the attrs keyword, the dict you pass to the Select2Widget() instance is unique and not shared between values in the resulting dictionary.
Just stick to your dict comprehension, it is working just fine.

Categories