How to make dictionary from list - python

My list:
list = ['name1', 'option1.1 value1.1', 'option1.2 value1.2', 'name2', 'option2.1 value2.1', 'option2.2 value2.2', 'option2.3 value2.3']
And i want create dictionary like this:
dict = {'name1':{'option1.1':'value1.1', 'option1.2':'value1.2'}, 'name2':{'option2.1': 'value2.1', 'option2.2':'value2.2', 'option2.3':'value2.3'}
I don't know how big is my list (numbers of names, options and values). Any idea?

with list and dict comprehension:
id=[b[0] for b in enumerate(lst) if 'name' in b[1]]+[None]
d={lst[id[i]]:dict(map(str.split,lst[id[i]+1:id[i+1]])) for i in range(len(id)-1)}
your original list was here named lst
This is perhaps not as readable as the answer by #sr22222, but perhaps it's faster, and a matter of taste.

Assuming name will always be a single token (also, don't use list and dict as variable names, as they are builtins):
result = {}
for val in my_list:
split_val = val.split()
if len(split_val) == 1:
last_name = split_val[0]
result[last_name] = {}
else:
result[last_name][split_val[0]] = split_val[1]
Note that this will choke if the list is badly formatted and the first value is not a name.

Related

Splitting a semicolon-separated with equal in a string

Below is the code:
s= "Name1=Value1;Name2=Value2;Name3=Value3"
dict(item.split("=") for item in s.split(";"))
I would like to understand how this works. Will it perform for loop first or will it split first?
List of dictionary
s1= "Name1=Value1,Name2=Value2,Name3=Value3;Name1=ValueA,Name2=ValueB,Name3=ValueC"
If you have python installed, I recommend using its interactive repl
With the repl you can run the parts of your program step by step:
s.split(";") will give you ['Name1=Value1', 'Name2=Value2', 'Name3=Value3']
['Name1=Value1', 'Name2=Value2', 'Name3=Value3']
item.split("=") for item in s.split(";") will give you a python generator that iterates on the the list from step 1 and split it off like into smaller lists like this:
[['Name1', 'Value1'], ['Name2', 'Value2'], ['Name3', 'Value3']]
Finally dict(...) on the pairs will turn them into key-value pairs in a python dictionary like this:
{'Name1': 'Value1', 'Name2': 'Value2', 'Name3': 'Value3'}
dict is being passed a generator expression, which produces a sequence of lists by first calling s.split(";"), then yielding the result of item.split("=") for each value in the result of the first split. A more verbose version:
s = "..."
d = dict()
name_value_pairs = s.split(";")
for item in name_value_pairs:
name_value = item.split("=")
d.update([name_value])
I use d.update rather than something simpler like d[x] = y because both dict and d.update can accept the same kind of sequence of key/value pairs as arguments.
From here, we can reconstruct the original by eliminating one temporary variable at a time, from
s = "..."
d = dict()
for item in s.split(";"):
name_value = item.split("=")
d.update(name_value)
to
s = "..."
d = dict()
for item in s.split(";"):
d.update([item.split("=")])
to
s = "..."
d = dict(item.split("=") for item in s.split(";"))
If you write it like that, you might understand better what's happening.
s= "Name1=Value1;Name2=Value2;Name3=Value3"
semicolon_sep = s.split(";")
equal_sep = [item.split("=") for item in semicolon_sep]
a = dict(equal_sep)
print(a["Name1"])
First, it splits the text from wherever there is a semicolon. In this way, we create a list with three elements as "semicolon_sep":
>>> print(semicolon_sep)
['Name1=Value1', 'Name2=Value2', 'Name3=Value3']
Then, it makes a loop over this list to separate each item wherever there is "=". In this way, we have 2 columns for each item (Name and Value). By putting this list (equal_sep) in dict() we change the list to a dictionary.

Converting nested lists to dictionary with self generated keys

My list of lists looks like this:
my_list = [[sub_list_1],[sub_list_2],...,[sub_list_n]]
Desired output
my_dict[1] = [sub_list_1]
my_dict[2] = [sub_list_2]
my_dict[n] = [sub_list_n]
I want the keys for the dictionary to be generated on their own. How can this be achieved in a pythonic way?
I look at certain questions like
Converting list of lists in dictionary python
Python: List of lists to dictionary
Converting nested lists to dictionary
but they either provide a list of keys or focus on using some information from the lists as keys.
Alternatively, I tried making a list of keys this way:
my_keys = list(range(len(my_list)))
my_dict = dict(zip(my_keys,my_list)
and it works but, this does not:
my_dict = dict(zip(list(range(len(my_list))),my_list))
This gives me a syntax error.
So in summary:
Is there a way to generate a dictionary of lists without explicitly providing keys?, and
Why does the combined code throw a syntax error whereas the two step code works?
I would recommend to use a dict comprehension to achieve what you want like in here, moreover I tried your implementation and haven't faced any issues (more details are more than welcome):
my_list = [["sub_list_1"],["sub_list_2"],["sub_list_3"]]
my_dict = dict(zip(list(range(len(my_list))),my_list))
alternative_dict = {iter:item for iter,item in enumerate(my_list)}
print("yours : " + str(my_dict))
print("mine : " + str(alternative_dict))
output:
yours : {0: ['sub_list_1'], 1: ['sub_list_2'], 2: ['sub_list_3']}
mine : {0: ['sub_list_1'], 1: ['sub_list_2'], 2: ['sub_list_3']}
Your syntax error is caused by your variable name try. try is allready a name in python. see try/except
This should do it
my_dict = {my_list.index(i) + 1: i for i in my_list}
Notice that I have added +1 to start at the key 1 instead of 0 to match your expectations
I received no error message when running your code:
>>> my_list = [["hello1"], ["hello2"]]
>>> my_dict = dict(zip(list(range(len(my_list))), my_list))
>>> my_dict
{1: ['hello1'], 2: ['hello2']}
You can create a dict of lists from a list of lists using a dict comprehension:
my_dict = {i: sub_list for i, sub_list in enumerate(my_list)}

How do I save changes made in a dictionary values to itself?

I have a dictionary where the values are a list of tuples.
dictionary = {1:[('hello, how are you'),('how is the weather'),('okay
then')], 2:[('is this okay'),('maybe It is')]}
I want to make the values a single string for each key. So I made a function which does the job, but I do not know how to get insert it back to the original dictionary.
my function:
def list_of_tuples_to_string(dictionary):
for tup in dictionary.values():
k = [''.join(i) for i in tup] #joining list of tuples to make a list of strings
l = [''.join(k)] #joining list of strings to make a string
for j in l:
ki = j.lower() #converting string to lower case
return ki
output i want:
dictionary = {1:'hello, how are you how is the weather okay then', 2:'is this okay maybe it is'}
You can simply overwrite the values for each key in the dictionary:
for key, value in dictionary.items():
dictionary[key] = ' '.join(value)
Note the space in the join statement, which joins each string in the list with a space.
It can be done even simpler than you think, just using comprehension dicts
>>> dictionary = {1:[('hello, how are you'),('how is the weather'),('okay then')],
2:[('is this okay'),('maybe It is')]}
>>> dictionary = {key:' '.join(val).lower() for key, val in dictionary.items()}
>>> print(dictionary)
{1: 'hello, how are you how is the weather okay then', 2: 'is this okay maybe It is'}
Now, let's go through the method
we loop through the keys and values in the dictionary with dict.items()
assign the key as itself together with the value as a string consisting of each element in the list.
The elemts are joined together with a single space and set to lowercase.
Try:
for i in dictionary.keys():
dictionary[i]=' '.join(updt_key.lower() for updt_key in dictionary[i])

How to get dictionary in python list matching a given criteria

I have list of dictionaries-
[{"id":1,"name":"abc"},{"id":2,"name":"def"},{"id":3,"name":"xyz"}]
I want to get the dictionary where id = 1 and store it in a variable.Something like-
element = {"id":1,"name":"abc"}
I don't want to use for loop to iterate through the list and then fetch the element.
No matter what you do, you'll have to iterate over that list.
g = (e for e in elements if e.get('id') == 1)
element = next(g)
The nice thing about this implementation is it only iterates as much as needed to find the next matching element.
The problem you are addressing is called indexing. If you don't know anything about your matching criterias a priori then there is nothing you can do and you have to do the loop. The easiest implementation would be:
my_obj = next(obj for obj in my_list if my_criterium(obj))
where in your case
my_criterium = lambda obj: obj['id'] == 1
However if you know that you will always search by id then you can create an index:
my_index = {obj['id']: obj for obj in my_list}
Then the retrieveing is as simple as
my_obj = my_index[1]
which no longer requires a loop (and thus is fast).
This is under assumption that id is unique on each object (this assumption is not crutial, you can create a different index by storing a list of matched element for each id). The other drawback is that it will be hard to keep both the index and the list consistent between each other.
But no matter what path you chose there is no escape from a loop.
Dicts = [{"id":1,"name":"abc"},{"id":2,"name":"def"},{"id":3,"name":"xyz"}]
for d in Dicts:
if d.get('id') == 1:
element = d
print element
You can store the ids of your dictionary-list into another dictionary using just one for loop. This will be much faster when you have multiple queries.
In [1]: d = [{"id":1,"name":"abc"},{"id":2,"name":"def"},{"id":3,"name":"xyz"}]
In [2]: indices = {v["id"] : index for index, v in enumerate(d)}
In [3]: element = d[indices[1]]
In [4]: print(element)
{'id': 1, 'name': 'abc'}
In [5]: element = d[indices[3]]
In [6]: print(element)
{'id': 3, 'name': 'xyz'}
I think I have a solution.
Basically, you convert the list into a string and then you play with it to make a single dictionary.
Although, I think that looping over the list is way better.
l = [{"id":1,"name":"abc"},{"id":2,"name":"def"},{"id":3,"name":"xyz"}]
#convert to string
a = str(l)
#remove parenthesis and curly brackets
a = a.replace('{','').replace('}','').replace('[','').replace(']','').replace(' ','')
#remove 'id' and 'name'
a = a.replace("'id':",'').replace(",'name'",'')
#add curly brackets
a = '{'+a+'}'
#make a dict
exec('a='+a)
>>>a
{1: 'abc', 2: 'def', 3: 'xyz'}
As you can see, you end up with a single dictionary with the right key/value pairs without using a single for loop!

python how to build a new list from this one

I have a list in the following format:
['CASE_1:a','CASE_1:b','CASE_1:c','CASE_1:d',
'CASE_2:e','CASE_2:f','CASE_2:g','CASE_2:h']
I want to create a new list which looks like like this:
['CASE_1:a,b,c,d','CASE_2:e,f,g,h']
Any idea how to get this done elegantly??
You can use a defaultdict by treating case as the key, and appending to the list each letter, where case and the letter are obtained by splitting the elements of your list on ':' - such as:
from collections import defaultdict
case_letters = defaultdict(list)
start = ['CASE_1:a','CASE_1:b','CASE_1:c','CASE_1:d', 'CASE_2:e','CASE_2:f','CASE_2:g','CASE_2:h']
for el in start:
case, letter = el.split(':')
case_letters[case].append(letter)
result = sorted('{case}:{letters}'.format(case=key, letters=','.join(values)) for key, values in case_letters.iteritems())
print result
As this is homework (edit: or was!!?) - I recommend looking at collections.defaultdict, str.split (and other builtin string methods), at the builtin type list and it's methods (such as append, extend, sort etc...), str.format, the builtin sorted method and generally a dict in general. Use the working example here along with the final manual for reference - all these things will come in handy later on - so it's in your best interest to understand them as best you can.
One other thing to consider is that having something like:
{1: ['a', 'b', 'c', 'd'], 2: ['e', 'f', 'g', 'h']}
is a lot more of a useful format and could be used to recreate your desired list afterwards anyway...
I've deleted my full solution since I realized this is homework, but here's the basic idea:
A dictionary is a better data structure. I would look at a collections.defaultdict. e.g.
yourdict = defaultdict(list)
You can iterate through your list (splitting each element on ':'). Something like:
#only split string once -- resulting in a list of length 2.
case, value = element.split(':',1)
Then you can add these to the dict using the list .append method:
yourdict[case].append(value)
Now, you'll have a dict which maps keys (Case_1, Case_2) to lists (['a','b','c','d'], [...]).
If you really need a list, you can sort the items of the dictionary and join appropriately.
sigh. It looks like the homework tag has been removed (here's my original solution):
from collections import defaultdict
d = defaultdict(list)
for elem in yourlist:
case, value = elem.split(':', 1)
d[case].append(value)
Now you have a dictionary as I described above. If you really want to get your list back:
new_lst = [ case+':'+','.join(values) for case,values in sorted(d.items()) ]
data = ['CASE_1:a','CASE_1:b','CASE_1:c','CASE_1:d', 'CASE_2:e','CASE_2:f','CASE_2:g','CASE_2:h']
output = {}
for item in data:
key, value = item.split(':')
if key not in output:
output[key] = []
output[key].append(value)
result = []
for key, values in output.items():
result.append('%s:%s' % (key, ",".join(values)))
print result
outputs
['CASE_2:e,f,g,h', 'CASE_1:a,b,c,d']
mydict = {}
for item in list:
key,value = item.split(":")
if key in mydict:
mydict[key].append(value)
else:
mydict[key] = [value]
[key + ":" + ",".join(value) for key, value in mydict.iteritems()]
Not much elegance, to be honest. You know, I'd store your list as a dict, cause it behaves as a dict in fact.
output is ['CASE_2:e,f,g,h', 'CASE_1:a,b,c,d']

Categories

Resources