I am checking the key in dictionary, if it contains space remove it.
def query_combination(sentence,mydict):
for key in mydict.keys():
if key == 'key':
pass
else:
print 'key is : ',key
if " " in key:
temp = key
key = key.replace(' ',"")
print 'new key : ',key
sentence = sentence.replace(temp ,key)
print 'new sentence : ',sentence
print mydict
mydict = {'films': {'match': ['Space', 'Movie', 'six', 'two', 'one']}, u'Popeye Doyle': {'score': 100, 'match': [u'People', 'heaven', 'released']}}
sentence ='What films featured the character Popeye Doyle'
combination = query_combination(sentence,mydict)
I could not dynamically change the new key value to mydict. Any suggestion much appreciable
If you get a string out of the dictionary, and then change it and make a new string, the dictionary won't know about it; you can add a new entry to the dictionary and remove the old one:
if " " in key:
newkey = key.replace(' ',"")
mydict[newkey] = mydict[key]
del mydict[key]
print 'new key : ', newkey
You could try this
def query_combination(sentence,mydict):
for key in mydict.iterkeys():
if " " in key:
temp = key
mydict[key.replace(" ","")] = mydict[key] # create new key
del mydict[key] # delete old key
sentence = sentence.replace(temp ,key)
Another solution in one line would be
mydict[key.replace(" ","")] = mydict.pop(key)
key = key.replace(' ',"") does not affect the actual key in the dictionary, it is changing a copy of that key. You need to add the value to the dictionary with the new key and remove the old key. Here's one way to do it:
def query_combination(sentence, mydict):
for old_key, new_key in [(key, key.replace(' ', '')) for key in mydict if ' ' in key]:
mydict[new_key] = mydict.pop(old_key)
sentence = sentence.replace(old_key, new_key)
Note, however, that you are replacing the key in the string sentence, but sentence is local to function query_combination(), so the outer scope sentence is unaffected by the replacement. I am not sure if that was what you hoped your code would do, but if it was you could simply return the revised sentence from the function, or include it as an item in the dictionary.
Given that sentence is not actually updated by your function, you can simplify the whole function to a mere dictionary comprehension:
>>> mydict = {'films': {'match': ['Space', 'Movie', 'six', 'two', 'one']}, u'Popeye Doyle': {'score': 100, 'match': [u'People', 'heaven', 'released']}}
>>> mydict = {key.replace(' ', '') : value for key, value in mydict.items()}
>>> mydict
{'films': {'match': ['Space', 'Movie', 'six', 'two', 'one']}, u'PopeyeDoyle': {'score': 100, 'match': [u'People', 'heaven', 'released']}}
Related
How can I match the key name from general_key_array with all_keys dictionary to get "aws." as substring? I added the startswith section but it returns True all the time.
general_keys = dict()
all_keys = {'activity': 'ins','install': 'all','aws.a': 'data', 'aws.b': 'data1', 'aws.c': 'data2'} #read from file
general_key_array = ['install', 'aws.']
for key in general_key_array:
if key.startswith(key) in all_keys:
general_keys[key] = dict(filter(lambda item: key in item[0], all_keys.items()))
You can do it all with a single dictionary comprehension.
general_keys = {key: value for key, value in all_keys.items()
if any(key.startswith(gk) for gk in general_key_array)}
key.startswith(key) is always equal to True because it's tautological that a string starts with itself.
you can add a for loop with the keys of all_keys after the first one you wrote to solve the problem like this
general_keys = dict()
all_keys = {'activity': 'ins','install': 'all','aws.a': 'data', 'aws.b': 'data1', 'aws.c': 'data2'}
general_key_array = ['install', 'aws.']
for key in general_key_array:
for s in all_keys :
if s.startswith(key): # s is part of all_keys, no tautology here
general_keys[key] = dict(filter(lambda item: key in item[0], all_keys.items()))
i use this code to store items of dictionaries in doc variable.
This code works fine but I miss the first element of time because of the if statement.
def convert(old):
time_key = 'Time '
# Save the time
time_item = (time_key, old[time_key])
# Add remove it
del old[time_key]
# Copy remaining items to new dicts and save them in a list
return [dict([time_item, item]) for item in old.items()]
row = {
'Time ': '2017-12-01T13:54:04',
'Energy [kWh]': '0.01',
'Voltage [V]': '221.64',
'Current [A]': '0.08',
}
new_data = convert(row)
#print(new_data)
Zeitvalue= ""
Device=""
Value=""
for d in new_data:
#print(d)
for key, value in d.items():
if key == 'Time ':
Zeitvalue = value
#print(value)
continue
else:
Device = key
Value = value
doc = {'Time ':Zeitvalue,'Device':Device, 'Measure':Value}
print("This is doc variable:",doc) # doc vaiable with missed time element
SO when i print doc i got this
Output:
doc: {'Device': 'Voltage [V]', 'Measure': '221.64', 'Time ': ''} # **ISSUE: variable time is missed here, How to fix it ?**
doc: {'Device': 'Current [A]', 'Measure': '0.08', 'Time ': '2017-12-01T13:54:04'}
doc: {'Device': 'Energy [kWh]', 'Measure': '0.01', 'Time ': '2017-12-01T13:54:04'}
See the below changes in the code. Remove continue statement. Also assign value to doc after the inner loop for dictionary is over as you need all three values.
for d in new_data:
#print(d)
for key, value in d.items():
if key == 'Time ':
Zeitvalue = value
#print(value)
else:
Device = key
Value = value
doc = {'Time ':Zeitvalue,'Device':Device, 'Measure':Value}
print(doc)
if you are just setting values then place the doc assignment outside the for loop
for d in new_data:
for key, value in d.items():
if key == 'Time ':
Zeitvalue = value
continue
else:
Device = key
Value = value
doc = {'Time ':Zeitvalue,'Device':Device, 'Measure':Value}
you have problem in this line:
doc = {'Time ':Zeitvalue,'Device':Device, 'Measure':Value} when you use it inside the for loop! , each iteration overrides the previous assignment, furthermore - you cause unexpected behavior , since dictionary is not order data structure - meaning : if you encountered "tine" key first - it will work fine , but if you did not encountered 'time' first - the value of it is still == "" , since you initiate it to that value and you did not updated it since.
move the doc = {'Time ':Zeitvalue,'Device':Device, 'Measure':Value} to the outer loop , and not the one going over each key and value and you will be fine.
please help
value = 'http://localhost:8001/issues/load?project_name=react&since=2016-03-24&until=2017-03-25&state=closed&sort=created&direction=asc&per_page=100&labels=Type:%20Bug'
hashing = hash(value)
words = value.split('&')
for data in words:
words2 = data.split('=')
print(words2)
Since words2 has each split into two like:
['http://localhost:8001/issues/load?project_name', 'react']
['since', '2016-03-24']
['until', '2017-03-25']
Use that to add values to a dictionary:
>>> key_vals = {}
>>> for data in words:
... words2 = data.split('=')
... key_vals[words2[0]] = words2[1]
...
>>> pprint.pprint(key_vals)
{'direction': 'asc',
'http://localhost:8001/issues/load?project_name': 'react',
'labels': 'Type:%20Bug',
'per_page': '100',
'since': '2016-03-24',
'sort': 'created',
'state': 'closed',
'until': '2017-03-25'}
And the assignment to key_vals can be reduced to:
key_vals = {key: val for (key, val) in [data.split('=') for data in words]}
I have a CSV file that I've filtered into a list and grouped. Example:
52713
['52713', '', 'Vmax', '', 'Start Value', '', '\n']
['52713', '', 'Vmax', '', 'ECNumber', '1.14.12.17', '\n']
['52713', 'O2', 'Km', 'M', 'Start Value', '3.5E-5', '\n']
['52713', 'O2', 'Km', 'M', 'ECNumber', '1.14.12.17', '\n']
52714
['52714', '', 'Vmax', '', 'Start Value', '', '\n']
['52714', '', 'Vmax', '', 'ECNumber', '1.14.12.17', '\n']
['52714', 'O2', 'Km', 'M', 'Start Value', '1.3E-5', '\n']
['52714', 'O2', 'Km', 'M', 'ECNumber', '1.14.12.17', '\n']
From this, I create a nested dictionary with the structure:
dict = ID number:{Km:n, Kcat:n, ECNumber:n}
...for every ID in the list.
I use the following code to create this dictionary
dict = {}
for key, items in groupby(FilteredTable1[1:], itemgetter(0)):
#print key
for subitem in items:
#print subitem
dict[subitem[EntryID]] = {}
dict[subitem[EntryID]]['EC'] = []
dict[subitem[EntryID]]['Km'] = []
dict[subitem[EntryID]]['Kcat'] = []
if 'ECNumber' in subitem:
dict[subitem[EntryID]]['EC'] = subitem[value]
if 'Km' in subitem and 'Start Value' in subitem:
dict[subitem[EntryID]]['Km'] = subitem[value]
#print subitem
This works for the ECNumber value, but not the Km value. It can print the line, showing that it identifies the Km value as being present, but doesn't put it in the dictionary.
Example output:
{'Km': [], 'EC': '1.14.12.17', 'Kcat': []}
Any ideas?
Ben
The problem is that your inner for loop keeps reinitializing dict[subitem[EntryID]] even though it may already exist. That's fixed in the following by explicitly checking to see if it's already there:
dict = {}
for key, items in groupby(FilteredTable1[1:], itemgetter(0)):
#print key
for subitem in items:
#print ' ', subitem
if subitem[EntryID] not in dict:
dict[subitem[EntryID]] = {}
dict[subitem[EntryID]]['EC'] = []
dict[subitem[EntryID]]['Km'] = []
dict[subitem[EntryID]]['Kcat'] = []
if 'ECNumber' in subitem:
dict[subitem[EntryID]]['EC'] = subitem[value]
if 'Km' in subitem and 'Start Value' in subitem:
dict[subitem[EntryID]]['Km'] = subitem[value]
#print subitem
However this code could be made more efficient by using something like the following instead, which avoids recomputing values and double dictionary lookups. It also doesn't use the name of a built-in type for a variable name, which goes against the guidelines given in the PEP8 - Style Guide for Python Code. It also suggests using CamelCase only for class names, not for variable names like FilteredTable1 — but I didn't change that.
adict = {}
for key, items in groupby(FilteredTable1[1:], itemgetter(0)):
#print key
for subitem in items:
#print ' ', subitem
entry_id = subitem[EntryID]
if entry_id not in adict:
adict[entry_id] = {'EC': [], 'Km': [], 'Kcat': []}
entry = adict[entry_id]
if 'ECNumber' in subitem:
entry['EC'] = subitem[value]
if 'Km' in subitem and 'Start Value' in subitem:
entry['Km'] = subitem[value]
#print subitem
Actually, since you're building a dictionary of dictionaries, it's not clear that there's any advantage to using groupby to do so.
I'm posting this to follow-up and extend on my previous answer.
For starters, you could streamline the code a little further by eliminating the need to check for preexisting entries simply making the dictionary being created a collections.defaultdict dict subclass instead of a regular one:
from collections import defaultdict
adict = defaultdict(lambda: {'EC': [], 'Km': [], 'Kcat': []})
for key, items in groupby(FilteredTable1[1:], itemgetter(0)):
for subitem in items:
entry = adict[subitem[EntryID]]
if 'ECNumber' in subitem:
entry['EC'] = subitem[value]
if 'Km' in subitem and 'Start Value' in subitem:
entry['Km'] = subitem[value]
Secondly, as I mentioned in the other answer, I don't think you're gaining anything by using itertools.groupby() to do this — except making the process more complicated than needed. This is a because basically what you're doing is making a dictionary-of-dictionaries whose entries can all be randomly accessed, so there's no benefit in going to the trouble of grouping them before doing so. The code below proves this (in conjunction with using a defaultdict as shown above):
adict = defaultdict(lambda: {'EC': [], 'Km': [], 'Kcat': []})
for subitem in FilteredTable1[1:]:
entry = adict[subitem[EntryID]]
if 'ECNumber' in subitem:
entry['EC'] = subitem[value]
if 'Km' in subitem and 'Start Value' in subitem:
entry['Km'] = subitem[value]
I'm struggling with a recursive merge problem.
Let's say I have:
a=[{'name':"bob",
'age':10,
'email':"bob#bla",
'profile':{'id':1, 'role':"admin"}},
{'name':"bob",
'age':10,
'email':"other mail",
'profile':{'id':2, 'role':"dba"},
'home':"/home/bob"
}]
and I need something to recursively merge entries. If value for an existing given key on the same level is different it appends the value to an array.
b = merge(a)
print b
{'name':"bob",
'age':10,
'email':["bob#bla","other mail"],
'profile':{'id':[1,2], 'role'=["admin", "dba"], 'home':"/home/bob"}
I wrote this code:
def merge(items):
merged = {}
for item in items:
for key in item.keys():
if key in merged.keys():
if item[key] != merged[key]:
if not isinstance(merged[key], list):
merged[key] = [merged[key]]
if item[key] not in merged[key]:
merged[key].append(item[key])
else:
merged[key] = item[key]
return merged
The output is:
{'age': 10,
'email': ['bob#bla', 'other mail'],
'home': '/home/bob',
'name': 'bob',
'profile': [{'id': 1, 'role': 'admin'}, {'id': 2, 'role': 'dba'}]}
Which is not what I want.
I can't figure out how to deal with recursion.
Thanks :)
As you iterate over each dictionary in the arguments, then each key and value in each dictionary, you want the following rules:
If there is nothing against that key in the output, add the new key and value to the output;
If there is a value for that key, and it's the same as the new value, do nothing;
If there is a value for that key, and it's a list, append the new value to the list;
If there is a value for that key, and it's a dictionary, recursively merge the new value with the existing dictionary;
If there is a value for that key, and it's neither a list nor a dictionary, make the value in the output a list of the current value and the new value.
In code:
def merge(*dicts):
"""Recursively merge the argument dictionaries."""
out = {}
for dct in dicts:
for key, val in dct.items():
try:
out[key].append(val) # 3.
except AttributeError:
if out[key] == val:
pass # 2.
elif isinstance(out[key], dict):
out[key] = merge(out[key], val) # 4.
else:
out[key] = [out[key], val] # 5.
except KeyError:
out[key] = val # 1.
return out
In use:
>>> import pprint
>>> pprint.pprint(merge(*a))
{'age': 10,
'email': ['bob#bla', 'other mail'],
'home': '/home/bob',
'name': 'bob',
'profile': {'id': [1, 2], 'role': ['admin', 'dba']}}