Get a list of values from a list of dictionaries? - python

I have a list of dictionaries, and I need to get a list of the values from a given key from the dictionary (all the dictionaries have those same key).
For example, I have:
l = [ { "key": 1, "Val1": 'val1 from element 1', "Val2": 'val2 from element 1' },
{ "key": 2, "Val1": 'val1 from element 2', "Val2": 'val2 from element 2' },
{ "key": 3, "Val1": 'val1 from element 3', "Val2": 'val2 from element 3' } ]
I need to get 1, 2, 3.
Of course, I can get it with:
v=[]
for i in l:
v.append(i['key'])
But I would like to get a nicer way to do so.

Using a simple list comprehension (if you're sure every dictionary has the key):
In [10]: [d['key'] for d in l]
Out[10]: [1, 2, 3]
Otherwise you'll need to check for existence first:
In [11]: [d['key'] for d in l if 'key' in d]
Out[11]: [1, 2, 3]

Related

how to create a dictionary having different number of values at different keys?

Question.1 ) I want to create a dictionary , it consist of 8 keys , some keys has 2 values and some keys have 3 values. how to create this kinda dictionary in python.
i been trying using nested loops , but my logic didn't worked.
Desired output
dict_a = { 1:[0,1], 2:[2,3], 3:[4,5], 4:[6,7], 5:[8,9], 6:[10,11], 7:[12,13,14], 8:[15,16,17] }
Question.2 ) If we successfully create the dict_a then, In the second part, i want to merge the multiple values of dict_a according to the dict_b,shown below.
for example :- In dict_b = { 1:[1,2], 2:[2,3]......} ,Here 1:[1,2] means I want to merge 1st and 2nd 'values' of dict_a dictionary, which will give me [0, 1, 2, 3]. similarly 2:[2,3] will give me [2,3,4,5]
dict_b = { 1:[1,2], 2:[2,3], 3:[3,4], 4:[4,5], 5:[5,6], 6:[6,7], 7:[7,8] }
I actually tried the above method successfully, but for two keys 7thand 8th in dict_a , i want to merge with first two values only, i.e when dict_b goes to it's 7th key 7:[7,8], i want the result to be [12,13,15,16] and not [12,13,14,15,16,17].
but the method i used below will merge all inevitably.
dict_a = { 1:[0,1], 2:[2,3], 3:[4,5], 4:[6,7], 5:[8,9], 6:[10,11], 7:[12,13,14], 8:[15,16,17] }
dict_b = { 1:[1,2], 2:[2,3], 3:[3,4], 4:[4,5], 5:[5,6], 6:[6,7], 7:[7,8] }
a_list = []
for i in dict_b:
tem = []
a_list.append(tem)
for j in dict_b[i]:
tem.extend(dict_a[j])
print(tem)
Desired output-
[0, 1, 2, 3]
[2, 3, 4, 5]
[4, 5, 6, 7]
[6, 7, 8, 9]
[8, 9, 10, 11]
[10, 11, 12, 13]
[12, 13, 15, 16]
If you only want to merge with the first 2 values, use a slice.
Change
tem.extend(dict_a[j])
to
tem.extend(dict_a[j][:2])

Efficiently find strings in list of lists of strings (Python)

I'm looking for an efficient way to find different strings in a list of string lists and return their indices. Here is the code:
inp = [ 'ans1', 'ans2', 'ans3' ]
output = [ [ 'aaa', 'ans1', 'bbb', 'ccc', 'ans2', 'ddd' ],
[ 'bbb', 'aaa', 'ans2', 'ddd', 'ans1', 'aaa' ],
[ 'ddd', 'ccc', 'ans2', 'ans1', 'aaa', 'bbb' ] ]
# expected result
# result = [ [ 1, 4, 3 ], [ 4, 2, 2 ], [ -1, -1, -1 ] ]
Those reported in the result are the indices for the position in the output list of each string in the inp list. For example, ans2 is at index 4 in the first sublist, index 2 in the second sublist, and index 2 in the third sublist. Similarly for ans1. ans3, however, does not appear in any sublist and, therefore, the returned index is -1.
What I'm looking for is an efficient way to do this computation (possibly in parallel?) while avoiding the classic for loops that this can clearly be done with.
Some considerations:
output has shape equal to [ len( inp ), L ], where L is the size of the dictionary. In this case L = 5.
You can try list comprehension:
result = [[o.index(s) if s in o else -1 for o in output] for s in inp]
print(result) # [[1, 4, 3], [4, 2, 2], [-1, -1, -1]]
Update:
Also it's probably not the best idea to store -1 as an index for strings, which are not presented in the output list. -1 is a valid index in Python, which may potentially lead to errors in the future if you plan to do something with indexes, stored in the result.
You can create dictionary index first to speed-up the search:
inp = ["ans1", "ans2", "ans3"]
output = [
["aaa", "ans1", "bbb", "ccc", "ans2", "ddd"],
["bbb", "aaa", "ans2", "ddd", "ans1", "aaa"],
["ddd", "ccc", "ans2", "ans1", "aaa", "bbb"],
]
tmp = [{v: i for i, v in enumerate(subl)} for subl in output]
result = [[d.get(i, -1) for d in tmp] for i in inp]
print(result)
Prints:
[[1, 4, 3], [4, 2, 2], [-1, -1, -1]]

list of dicts - change key values from one to many to many to one

with a list of dict, say list1 like below
[
{'subId': 0, 'mainIds': [0]},
{'subId': 3, 'mainIds': [0, 3, 4, 5], 'parameter': 'off', 'Info': 'true'}
]
Need to convert to below format.
[
{'mainId': 0, 'subIds':[0,3]},
{'mainId': 3, 'subIds': [3] },
{'mainId': 4, 'subIds': [3] },
{'mainId': 5, 'subIds': [3]}
]
What is tried so far
finalRes = []
for i in list1:
subId = i['subId']
for j in i['mainIds']:
res = {}
res[mainId] = j
res['subIds'] = []
res['subIds'].append(subId)
finalRes.append(res)
This gives something closer to the required output. Need help with getting the output mentioned above. Is there any popular name for this kind of operation (something like one to many to many to one ?)
[
{'mainId': 0, 'subIds':[0]},
{'mainId': 0, 'subIds':[3]}
{'mainId': 3, 'subIds': [3]},
{'mainId': 4, 'subIds': [3]},
{'mainId': 5, 'subIds': [3]}
]
This kinds of joins can be implemented easily with defaultdict:
subs_by_main_id = defaultdict(list)
for entry in list1:
sub_id = entry['subId']
for main_id in entry['mainIds']:
subs_by_main_id[main_id].append(sub_id)
return [{'mainId': main_id, 'subIds': sub_ids}
for main_id, sub_ids in sub_by_main_id.items()]
Here's a solution using comprehensions and itertools.chain. Start by converting the lists to sets, for fast membership tests; then build the result directly. It is not as efficient as the defaultdict solution.
from itertools import chain
sets = { d['subId']: set(d['mainIds']) for d in data }
result = [
{'mainId': i, 'subIds': [ j for j, v in sets.items() if i in v ]}
for i in set(chain.from_iterable(sets.values()))
]

Python 3: How to compare two tuples and find similar values?

I have two dictionaries: (1)Inventory and (2)Items
Under these dictionaries are tuples which are added using user's input.
dict_inventory = {('fruits', ['apple','mango'])
dict_items = {('apple', [3, 5])
('mango', [4, 6])}
How do I compare the two and to match similar values which are apple and mango
My code is not printing anything:
for itemA in dict_inventory.values():
for itemB in dict_items.keys():
if itemA == itemB:
print("Match!")
Your original for-loop was getting the values from the inventory dictionary as a list rather than a string when you iterated through the values. Since it returned a list, you will need to iterate through those values as well. This should get you running:
inventory = {
"fruits": ["apples", "mangos",]
}
items = {
"apples": [3, 5],
"mangos": [4, 6],
}
for value in inventory.values():
for item_a in value:
if item_a in items.keys():
print("Match!")
However, you could just merge the two dictionaries.
inventory = {
"fruits": {
"apples": [3, 5],
"mangos": [4, 6],
}
}

Traverse a dictionary recursively in Python?

What is the better way to traverse a dictionary recursively?
Can I do it with lambda or/and list comprehension?
I have:
[
{
"id": 1,
"children": [
{
"id": 2,
"children": []
}
]
},
{
"id": 3,
"children": []
},
{
"id": 4,
"children": [
{
"id": 5,
"children": [
{
"id": 6,
"children": [
{
"id": 7,
"children": []
}
]
}
]
}
]
}
]
I want:
[1,2,3,4,5,6,7]
You can recursively traverse your dictionaries, with this generic generator function, like this
def rec(current_object):
if isinstance(current_object, dict):
yield current_object["id"]
for item in rec(current_object["children"]):
yield item
elif isinstance(current_object, list):
for items in current_object:
for item in rec(items):
yield item
print list(rec(data))
# [1, 2, 3, 4, 5, 6, 7]
The easiest way to do this will be with a recursive function:
recursive_function = lambda x: [x['id']] + [item for child in x['children'] for item in recursive_function(child)]
result = [item for topnode in whatever_your_list_is_called for item in recursive_function(topnode)]
My solution:
results = []
def function(lst):
for item in lst:
results.append(item.get('id'))
function(item.get('children'))
function(l)
print results
[1, 2, 3, 4, 5, 6, 7]
The dicter library can be useful. You can easily flatten or traverse the dictionary paths.
pip install dicter
import dicter as dt
# Example dict:
d = {'level_a': 1, 'level_b': {'a': 'hello world'}, 'level_c': 3, 'level_d': {'a': 1, 'b': 2, 'c': {'e': 10}}, 'level_e': 2}
# Walk through dict to get all paths
paths = dt.path(d)
print(paths)
# [[['level_a'], 1],
# [['level_c'], 3],
# [['level_e'], 2],
# [['level_b', 'a'], 'hello world'],
# [['level_d', 'a'], 1],
# [['level_d', 'b'], 2],
# [['level_d', 'c', 'e'], 10]]
The first column is the key path. The 2nd column are the values. In your case, you can take in the 1st column all last elements.

Categories