There is a weird string representation like
"key1:value1:key2:value2:key3:value3...keyn:valuen"
I need to create a dict and it's pretty easy to solve when you have commas, however there is only colons here and you have to split the string every second colon. Code with cycle or soemthing like that looks pretty ugly, so I wonder if you could help me with oneliner.
You can just split on colons, get an iterator over the tokens and zip the iterator with itself. That will pair keys and values nicely:
s = 'key1:value1:key2:value2:key3:value3:keyn:valuen'
it = iter(s.split(':'))
dict(zip(it, it))
# {'key1': 'value1', 'key2': 'value2', 'key3': 'value3', 'keyn': 'valuen'}
If you are uncomfortable with iter (and schwobaseggls solutions wich I deem superior), you can use zipped list-slices in almost the same way:
s = 'key1:value1:key2:value2:key3:value3:keyn:valuen'
splitted = s.split(':')
# even_elements = splitted[::2] - take every 2nd starting at 0th index
# odd_elements = splitted[1::2] - take every 2nd startIng at 1st index
k = {k:v for k,v in zip(splitted[::2],splitted [1::2]) }
print(k)
Output:
{'key1': 'value1', 'key2': 'value2', 'key3': 'value3', 'keyn': 'valuen'}
Alternativly, you create the dict by hand:
s = 'key1:value1:key2:value2:key3:value3:keyn:valuen'
splitted = s.split(':')
d ={}
# this generates 2-slices from the list and puts them into your dict
for k,v in (splitted[i:i+2] for i in range(0,len(splitted),2)):
d[k] = v
# or d = { k:v for k, v in (splitted[i:i+2] for i in range(0,len(splitted),2) )}
# or d = dict(splitted[i:i+2] for i in range(0,len(splitted),2) )
print(d)
Output:
{'key1': 'value1', 'key2': 'value2', 'key3': 'value3', 'keyn': 'valuen'}
Related
Very similar to this question but with an added caveat.
I have two lists identical in length. One contains my keys, and the other contains a list of dictionaries belonging to said keys. Example below (yes the Nones are intentional)
keys = ['key1', 'key2, 'key3']
vals = [[{'subkey1': 'val1', 'subkey2': 'val2'}], [{'subkey1: 'val2'},None],[{'subkey1':'val3'}, {'subkey3':'val1}, None, None]]
What I'd like to do is match each dictionary in each list to a key to create a nested dict.
So something like below:
final = {'key1':{'subkey1': 'val1', 'subkey2': 'val2'}, 'key2':{'subkey1': 'val2'}, 'key3':{'subkey1':'val3'}, {'subkey3':'val1'}}
I know we can use dictionary comprehension to do this. I created a dictionary of empty dicts.
s = {}
for i in keys:
for v in vals:
s[i] = {}
break
Then I wrote the following to iterate through the list of dicts I'd like to pair up accounting for the non dictionary values in my list.
x = 0
while x < len(keys):
for i in keys:
for element in vals[x]:
if isinstance(element, dict) == True:
s[str(i)].append(element)
else:
print('no')
x=x+1
However when I run this, I get AttributeError: 'NoneType' object has no attribute 'append'
How can I append to a dictionary using this for loop?
For the less readable dictionary comprehension solution
keys = ['key1', 'key2', 'key3']
vals = [
[{'subkey1': 'val1', 'subkey2': 'val2'}],
[{'subkey1': 'val2'}, None],
[{'subkey1': 'val3'}, {'subkey3':'val1'}, None, None]
]
s = {
k: {
sk: sv for d in (x for x in v if x is not None) for sk, sv in d.items()
} for k, v in zip(keys, vals)
}
Gives
{'key1': {'subkey1': 'val1', 'subkey2': 'val2'},
'key2': {'subkey1': 'val2'},
'key3': {'subkey1': 'val3', 'subkey3': 'val1'}}
This can be done fairly easily using a defaultdict:
from collections import defaultdict
keys = ['key1', 'key2', 'key3']
vals = [
[{'subkey1': 'val1', 'subkey2': 'val2'}],
[{'subkey1': 'val2'},None],
[{'subkey1':'val3'}, {'subkey3':'val1'}, None, None]
]
final = defaultdict(dict)
for idx, key in enumerate(keys):
for d in vals[idx]:
if d is not None:
final[key].update(d)
Output:
defaultdict(<class 'dict'>, {
'key1': {'subkey1': 'val1', 'subkey2': 'val2'},
'key2': {'subkey1': 'val2'},
'key3': {'subkey1': 'val3', 'subkey3': 'val1'}
})
can't use append on a dict
try this maybe?
keys = ['key1', 'key2', 'key3']
vals = [[{'subkey1': 'val1', 'subkey2': 'val2'}], [{'subkey1': 'val2'},None],[{'subkey1':'val3'}, {'subkey3':'val1'}, None, None]]
s = {}
for i in keys:
s[i] = {}
for i, key in enumerate(keys):
for element in vals[i]:
if isinstance(element, dict) == True:
s[str(key)].update(element)
print(s)
Output:
{'key1': {'subkey1': 'val1', 'subkey2': 'val2'}, 'key2': {'subkey1': 'val2'}, 'key3': {'subkey1': 'val3', 'subkey3': 'val1'}}
I want to create a dictionary from a string that have key=value
s = "key1=value1 key2=value2 key3=value3"
print({r.split("=") for r in s})
Is it possible using dictionary comprehension? If yes, how?
You can first split on whitespace, then split on '='
>>> dict(tuple(i.split('=')) for i in s.split())
{'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
You could use map:
>>> s = "key1=value1 key2=value2 key3=value3"
>>> d = {k: v for k, v in map(lambda i: i.split('='), s.split())}
>>> {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
Lets say I have a nested dictionary
nested_dict={"dict1":{"key1":"value1", "key2":"value2", "key3":"value3;value4"}}
Now I want to split value3 and value 4 under the same key like this,
nested_dict={"dict1":{"key1":"value1", "key2":"value2", 'key3': ['value3', 'value4']}}
What would be the best way to do so in Python?
use the fact that dict is mutable and you can recursively change anything under the sun :P
nested_dict={"dict1":{"key1":"value1", "key2":"value2", "key3":"value3;value4"}}
def sol(d):
for i in d:
if type(d[i]) is dict:
sol(d[i])
else:
d[i] = d[i].split(';')
if len(d[i])==1: d[i] = d[i][0]
sol(nested_dict)
print(nested_dict)
{'dict1': {'key1': 'value1', 'key2': 'value2', 'key3': ['value3', 'value4']}}
How would one go about cleaning a dictionary containing a variety of datatypes of nulls and empty lists, dicts etc. E.g.
raw = {'key': 'value', 'key1': [], 'key2': {}, 'key3': True, 'key4': None}
To:
refined = {'key': 'value', 'key3': true}
Because of the mixed nature of data types in the dictionary, using:
refined = {k:v for k,v in processed.items() if len(v)>0}
throws a
TypeError: object of type 'bool' has no len()
Is there a solution to make a second conditional based on type(v) is bool?
Edit: I've found the issue I was encountering employing solutions was a result of the structure of the data, asking a separate question to deal with that.
You can try this.
refined={k:v for k,v in raw.items() if v or isinstance(v,bool)}
raw={'key': 'value',
'key1': [],
'key2': {},
'key3': True,
'key4': None,
'key5': False}
refined={k:v for k,v in raw.items() if v or isinstance(v,bool)}
#{'key': 'value', 'key3': True, 'key5': False}
How about
refined = {k:v for k, v in processed.items() v is not None and (type(v) not in (list, dict) or len(v) > 0)}
I have a dictionary like this
dict1 = {'key1': 'value1', 'key2': 'value2'}
how do I have an array of the keys and values as dictionaries like this
array_of_dict_values = [{'key1': 'value1'}, {'key2': 'value2'}]
What would be the easiest way to accomplish this?
You can do this:
>>> aDict = {'key1': 'value1', 'key2': 'value2'}
>>> aList = [{k:v} for k, v in aDict.items()]
>>> aList
[{'key2': 'value2'}, {'key1': 'value1'}]
While somebody already answered with how to do this, I'm going to answer with "you probably don't want to do this." If every entry is a dictionary with a single key, wouldn't a list of key-value pairs work just as well?
dictionary = {'key1': 'value1', 'key2': 'value2'}
print(list(dictionary.items()))
# [('key2', 'value2'), ('key1', 'value1')]