copying multi-level Python dictionaries - python-2.7

I have below Python dictionary as source
d1 = {
'a': 1,
'b': 2,
'c': [{'d': 3, 'e': 4, 'un': 'wanted1', 'dont': 'needthis1'},
{'d': 5, 'e': 6, 'un': 'wanted2', 'dont': 'needthis2'}]
'xyz': 'abc',
'zxy': 'cab',
'wva': 'xyw'
}
And I want to copy the values of some specific keys to a different dict to form below target dictionary
d2 = {
'some_attr_1': 1,
'some_attr_x': 2,
'attr_some_z': [{'attr_x': 3, 'attrib': 4},
{'attr_x': 5, 'attrib': 6}]
}
Note:
I am not interested in all the attributes from source
for ex: I don't need keys xyz, zxy, etc
Basically, Want values for some keys in source to be mapped
to different keys in target dictionary.
My current approach is as below to have mapping between source and target dictionary keys.
attr_map1 = {
'some_attr_1': 'a',
'some_attr_x': 'b'
}
attr_map2 = {
'attr_x': 'd',
'attrib': 'e',
}
d2 = dict()
for k, v in attr_map1.items():
d2[k] = d1[v]
l1 = list()
for d_elem in d1['c']:
temp_dict = dict()
for k, v in attr_map2.items():
temp_dict[k] = d_elem[v]
l1.append(temp_dict)
d2['attr_some_z'] = l1
Is there any alternate, better and speedy approach to achieve this?
I am looking for a solution in Python 2.7.
thanks,

You can use recursion:
d1 = {'a': 1, 'b': 2, 'c': [{'d': 3, 'e': 4}, {'d': 5, 'e': 6}]}
def build(d):
return {f't_{a}':b if not isinstance(b, (dict, list)) else
list(map(build, b)) if isinstance(b, list) else build(b) for a, b in d.items()}
print(build(d1))
Output:
{
't_a': 1,
't_b': 2,
't_c': [
{'t_d': 3, 't_e': 4},
{'t_d': 5, 't_e': 6}
]
}
Edit: to run this solution in Python2, replace the f-string with simple concatenation:
d1 = {'a': 1, 'b': 2, 'c': [{'d': 3, 'e': 4}, {'d': 5, 'e': 6}]}
def build(d):
return {'t_'+a:b if not isinstance(b, (dict, list)) else
list(map(build, b)) if isinstance(b, list) else build(b) for a, b in d.items()}

Related

Iterating over maps in List and matching value in Dart

please help with code to print value of key c by comparing key value of a and b
the output should be 29
int a = 3;
int b = 6;
List nums = [
{'a': 1, 'b': 6, 'c': 9},
{'a': 1, 'b': 7, 'c': 10},
{'a': 3, 'b': 8, 'c': 19},
{'a': 3, 'b': 6, 'c': 29},
{'a': 2, 'b': 7, 'c': 39},
{'a': 2, 'b': 8, 'c': 49},
];
As per https://api.dart.dev/stable/2.16.2/dart-core/Iterable/where.html
void main() {
int a = 3;
int b = 6;
List nums = [
{'a': 1, 'b': 6, 'c': 9},
{'a': 1, 'b': 7, 'c': 10},
{'a': 3, 'b': 8, 'c': 19},
{'a': 3, 'b': 6, 'c': 29},
{'a': 2, 'b': 7, 'c': 39},
{'a': 2, 'b': 8, 'c': 49},
];
print(nums.where((m) => m['a'] == a && m['b'] == b));
print(nums.where((m) => m['a'] == a && m['b'] == b).elementAt(0)['c']);
}
the output will be
({a: 3, b: 6, c: 29})
29
The following code will output 29.
main(){
int a = 3;
int b = 6;
List nums = [
{'a': 1, 'b': 6, 'c': 9},
{'a': 1, 'b': 7, 'c': 10},
{'a': 3, 'b': 8, 'c': 19},
{'a': 3, 'b': 6, 'c': 29},
{'a': 2, 'b': 7, 'c': 39},
{'a': 2, 'b': 8, 'c': 49},
];
for(var item in nums){
if(item['a'] == a && item['b'] == b){
print(item['c']); // => 29
}
}
}

How to get specific values from a dictionary using list comprehension and modify them?

Can someone help and kindly advise how Can I get specific values from this dictionary (Using list comprehension) and
square the values only,
change every string value, so it starts with upper case?
items_list = {'a': 3, 'b':6, 'c': 'short', 'h': 'example', 'p': 77}
So, the output needs to be:
9, 36, 5929
Short, Example
(Python):
items_list = {'a': 3, 'b': 6, 'c': 'short', 'h': 'example', 'p': 77}
lst = [v ** 2 if isinstance(v, (int, float)) else v.capitalize() for v in
items_list.values()]
print(lst)
output:
[9, 36, 'Short', 'Example', 5929]
The exact output that you showed can not be produced using single list comprehension, because the iteration is in order.
yes, you need to iterate through the dictionary and check if the value is an int then square it and if it is not capitalize it
result = []
for key, value in dictionary.items()
if type(value) is int:
result.append(value**2)
else:
result.append(value.capitalize())
print(result)
this should print the desired output

merge x python dictionaries into 1 with aggregated values

I have a list of dictionaries with the same key names, I want to consolidate the dictionaries into one dictionary with averaged values only in number-based values:
[{'a': 3, 'b': 'm', 'c': 7},
{'a': 1.0, 'b': 'm', 'c': 2},
{'a': 5, 'b': 'm', 'c': 4.0}]
into an averaged dictionary:
[{'a': 3, 'b': 'm', 'c': 4}]
If you can assume you have at least one dict in the list and all the dicts have all the keys you can do:
import numbers
dicts =[{'a': 3, 'b': 'm', 'c': 7},
{'a': 1.0, 'b': 'm', 'c': 2},
{'a': 5, 'b': 'm', 'c': 4.0}]
avg_dict = {}
for key in dicts[0]:
avg_dict[key] = sum([d[key] for d in dicts])/len(dicts) if isinstance(dicts[0][key], numbers.Number) else dicts[0][key]
Maybe not the most pythonic way, but it will do the job:
lst = [{'a': 3, 'b': 'm', 'c': 7},
{'a': 1.0, 'b': 'm', 'c': 2},
{'a': 5, 'b': 'm', 'c': 4.0}]
result = {}
for item in lst:
for j in item:
if type(item[j]) == str:
result[j] = item[j]
elif j in result:
result[j] += item[j]
else:
result[j] = item[j]
for i in result:
if type(result[i]) != str:
result[i] = int(result[i] / len(lst))
print(result)

How to take the text of novel as raw_input and put it in ''' '''

def hashStory():
message = raw_input('Enter Story')
dictionary = {}
for i in message.upper():
dictionary.setdefault(i, 0)
dictionary[i] = dictionary[i] + 1
return dictionary
this code, when used on short strings like 'Hello, how are you', returns this.
{'A': 1, ' ': 3, 'E': 2, 'H': 2, 'L': 2, 'O': 3, 'R': 1, 'U': 1, 'W': 1, 'Y': 1}
But when I want to hash the letters in a story such as this.
RomeoAndJuliet
the punctuation gets in the way. How can I use raw_input to take the words in triple quotes.

slice a dictionary on elements contained within item arrays

Say I have a dict of country -> [cities] (potentially an ordered dict):
{'UK': ['Bristol', 'Manchester' 'London', 'Glasgow'],
'France': ['Paris', 'Calais', 'Nice', 'Cannes'],
'Germany': ['Munich', 'Berlin', 'Cologne']
}
The number of keys (countries) is variable: and the number of elements cities in the array, also variable. The resultset comes from a 'search' on city name so, for example, a search on "San%" could potentially meet with 50k results (on a worldwide search)
The data is to be used to populate a select2 widget --- and I'd like to use its paging functionality...
Is there a smart way to slice this such that [3:8] would yield:
{'UK': ['Glasgow'],
'France': ['Paris', 'Calais', 'Nice', 'Cannes'],
'Germany': ['Munich']
}
(apologies for the way this question was posed earlier -- I wasn't sure that the real usage would clarify the issue...)
If I understand your problem correctly, as talked about in the comments, this should do it
from pprint import pprint
def slice_dict(d,a, b):
big_list = []
ret_dict = {}
# Make one big list of all numbers, tagging each number with the key
# of the dict they came from.
for k, v in d.iteritems():
for n in v:
big_list.append({k:n})
# Slice it
sliced = big_list[a:b]
# Put everything back in order
for k, v in d.iteritems():
for subd in sliced:
for subk, subv in subd.iteritems():
if k == subk:
if k in ret_dict:
ret_dict[k].append(subv)
else:
ret_dict[k] = [subv]
return ret_dict
d = {
'a': [1, 2, 3, 4],
'b': [5, 6, 7, 8, 9],
'c': [10, 11, 12, 13, 14]
}
x = slice_dict(d, 3, 11)
pprint(x)
$ python slice.py
{'a': [4], 'b': [5, 6], 'c': [10, 11, 12, 13, 14]}
The output is a little different from your example output, but that's because the dict was not ordered when it was passed to the function. It was a-c-b, that's why b is cut off at 6 and c is not cut off