Iterate over a list inside a nested dictionary - python

Lets say I have a dictionary like this:
myDict = {
1: {
"a": "something",
"b": [0, 1, 2],
"c": ["a", "b", "c"]
},
2: {
"a": "somethingElse",
"b": [3, 4, 5],
"c": ["d", "e", "f"]
},
3: {
"a": "another",
"b": [6, 7, 8],
"c": ["g", "h", "i"]
}
}
And this is my code:
for id, obj in myDict.items():
for key, val in obj.items():
if key is "b":
for item in val:
# apply some function to item
Is there a better way to iterate over a list inside a nested dict? Or is there a pythonic way to do this?

You absolutely do not need to iterate the list to print it (unless this is a functional requirement for the code you are writing).
Very simply, you could do this:
for id, obj in myDict.items():
if "b" in obj:
print obj["b"]
To map the list object, represented by obj['b'] to another function, you can use the map function:
map(foo, obj["b"])

If you're dictionary is always two levels deep, I don't see anything wrong with your approach. In your implementation, I would use key == "b" rather than key is "b". Using is will test for identity (e.g. id(a) == id(b)), while == will test for equality (e.g. a.__eq__(b)). This functions the same way when I test it in IDLE, but it's not a good habit to get into. There's more info on it here: How is the 'is' keyword implemented in Python?
If you want to deal with varying level dictionaries, you could use something like:
def test_dict_for_key(dictionary, key, function):
for test_key, value in dictionary.items():
if key == test_key:
dictionary[key] = type(value)(map(function, value))
if isinstance(value, dict):
test_dict_for_key(value, key, function)
An example usage might be something like:
myDict = {
1: {
"a": "something",
"b": [0, 1, 2],
"c": ["a", "b", "c"]
},
2: {
"a": "somethingElse",
"b": [3, 4, 5],
"c": ["d", "e", "f"]
},
3: {
"a": "another",
"b": [6, 7, 8],
"c": ["g", "h", "i"]
}
}
# adds 1 to every entry in each b
test_dict_for_key(myDict, "b", lambda x: x + 1)
# prints [1, 2, 3]
print(myDict[1]["b"])

I'm a fan of generator expressions.
inner_lists = (inner_dict['b'] for inner_dict in myDict.values())
# if 'b' is not guaranteed to exist,
# replace inner_dict['b'] with inner_dict.get('b', [])
items = (item for ls in inner_lists for item in ls)
Now you can either use a foo loop
for item in items:
# apply function
or map
transformed_items = map(func, items)

A couple fixes could be made.
Don't use is when comparing two strings (if key is "b":)
Simply say print(item) instead of using .format(), since you only have one variable that you're printing, with no additional string formatting
Revised code:
for id, obj in myDict.items():
for key, val in obj.items():
if key == "b":
for item in val:
print(item)

If you are sure that you will have a b key in every case, you can simply do:
for id, obj in myDict.items():
for item in obj["b"]:
print item

Related

Switching keys of a dictionary without switching the values

Let's say I have a dictionary like below
myDict = {"a": 1, "b": 2, "c": 3, "d": 4}
and I'm trying to get this result
myDict = {"b": 1, "a": 2, "c": 3, "d": 4}
I tried running using
dictionary[new_key] = dictionary.pop(old_key)
But thats just deleting and appending a new key and value to the dictionary. It would result in:
myDict = {"b": 2, "c": 3, "d": 4, "a": 2}
Thanks in advance for the answer
So I understand you aim to preserve the sequence.
Make first a new dictionary that maps the old keys to the new keys:
mapping = {"a": "b", "b": "a"}
Now you can generate the new structure
my_dict = {mapping.get(key, key): value for key, value in my_dict.items()}
The get method here tries to map the key, but uses the key itself, if the key is not in the mapping.

how to keep count of each items in list - python [duplicate]

This question already has answers here:
How do I count the occurrences of a list item?
(29 answers)
Closed 10 months ago.
i was trying to keep count of each item in list in python and want to convert it into key-value pairs like json so i can able to iterate over it to present it on frontend using django.
list = ["a" , "a", "c", "b", "c", "d"]
here same i want this list into key value pairs with counting of each item in list
list = [{ "name":"a" , "count":2 } , { "name":"c" , "count":2 , ......}]
Use a set to count the number of each element in the list
l = ["a" , "a", "c", "b", "c", "d"]
d = {val: l.count(val) for val in set(l)}
this will give you :
{'c': 2, 'a': 2, 'b': 1, 'd': 1}
If you want to format the dict as you wrote it in your message (even though it's really inefficient), you can write it like that :
d = [{'name': val, 'count': l.count(val)} for val in set(l)}]
data = ["a" , "a", "c", "b", "c", "d"]
count_list=[{"name":d,"count": data.count(d)} for d in set(data)]
Probably the easiest way to do this:
def dict_count(list):
dict_tot = {}
for i in liste:
dict_tot[i] = liste.count(i)
print(dict_tot)

comparing inner dictionaries in Python

I am trying to create a Python function that receives a dictionary whose values are inner dictionaries. If the keys of the inner dictionaries are the same, it should return 1, if not it should return 0.
This is the code I tried:
def f(dct: dict) -> int:
for i in range(len(dct)):
for j in range(len(dct)):
dct1 = list(dct.values())
if dct1[i].keys() == dct1[j].keys():
return 1
else:
return 0
it actually worked when the input dictionary have only two inner dictionaries but didn't work for three.
For example:
f(
{
"A": {1: "a", 2: "b"},
"B": {2: "c", 3: "d"},
}
)
returned 0 (which is the result I wanted)
but
f(
{
"A": {1: "a", 2: "b"},
"B": {2: "c", 3: "d"},
"C": {1: "c", 2: "d"},
}
)
returned 1, which is not the result I wanted.
How do I fix it, please?
So you want to ensure all of the dictionaries that are the values of dct have the same keys (ignoring the values)?
def all_key_sets_equal(dct: dict) -> bool:
key_sets = [set(nd) for nd in dct.values()]
return all(key_set == key_sets[0] for key_set in key_sets)

Converting a dataset from one for to another

I have one dataset in a list form and I want to convert it into another dataset under certain conditions.
Conditions
"a" = 1
"b" = 2
"c" = 3
input_list = ["a", "b", "c"]
# something happens
output_list = [1, 2, 3]
What to do?
Represent your set of conditions in a dictionary:
conditions = {
"a": 1,
"b": 2,
"c": 3
}
Use that dictionary in order to generate the output:
input_list = ["a", "b", "c"]
output_list = [conditions[x] for x in input_list]
What you want to achieve is a mapping.
Your conditions are a map, dictionary (Python lingo) or hash-table.
Each value there (like 1) corresponds to a key in the dataset (like "a").
To represent this mapping you can use a table-like datastructure that maps a key to a value. In Python this datastructure is called a dictionary:
mapping = {"a": 1, "b": 2, "c": 3} # used to translate from key to value (e.g. "a" to 1)
input_list = ["a", "b", "c"]
# something happens
output_list = []
for v in input_list:
mapped_value = mapping[v] # get the corresponding value, translate or map it
print(v + " -> " + mapped_value)
output_list.append(mapped_value)
print(output_list) # [1, 2, 3]
See also
Map (mathematics) - Wikipedia
Convert numbers into corresponding letter using Python

How to dynamically move inside a nested dict in Python

I have a dict with a dynamical number of nested dicts inside of it, something like:
my_dict = {"a": {"b": {"c: {...}}}}
I need to dynamically move inside this dict, for instance I'd like to do the following:
levels = ["a", "b", "c"]
my_dict[levels[0]][levels[1]][levels[2]] = "something"
where the number of items inside "levels" may vary.
I can partially achieve the same result for a limited number of items inside "levels" by writing something like this:
if len(levels) == 1:
my_dict[levels[0]] = "something"
elif len(levels) == 2:
my_dict[levels[0]][levels[1]] = "something"
elif len(levels) == 3:
my_dict[levels[0]][levels[1]][levels[2]] = "something"
(...)
but I'm looking for a more general and elegant solution.
Is there a way to do this?
There isn't a lot of code here to go on, but for what you have given, you can define
def get(d, keys):
for key in keys:
d = d[key]
return d
def set(d, keys, value):
d = get(d, keys[:-1])
d[keys[-1]] = value
And then use it like this
my_dict = {"a":{"b":{"c":{}}}}
set(my_dict, ["a", "b", "c"], "something")
print get(my_dict, ["a", "b", "c"])
A functional alternative for get:
def get(d, keys):
return reduce(lambda d, key: d[key], keys, d)

Categories

Resources