How to convert the list into a list of dictionaries? - python

I have a list like this.
ls = ['Size:10,color:red,', 'Size:10,color: blue,']
I want to convert the list into this format.
[{'Size':'10','color':'red'}, {'Size':'10','color': 'blue'}]
What I have tried is:
[dict([pair.split(":", 1)]) for pair in ls]
# It gave me output like this.
[{'Size': '10,color:red,'}, {'Size': '10,color: blue,'}]
But this method works if the list is like this ['color:blue,'] but didn't worked properly with the above list.

We can see that for pair in ls in your list comprehension is already doubtful, because elements of ls are not pairs. Each element actually contains a sequence of pairs.
There will be two loops needed here, one to iterate the outer list, and then another one to iterate within each value, since those values are actually strings consisting of multiple fields.
While this is possible with a nested list comprehension, it will be easier (and more readable) if you break the problem down into simpler parts rather than trying to fit it all into one-line.
result = []
for text in ls:
d = {}
pairs = text.strip(",").split(",")
for pair in pairs:
key, val = pair.split(":")
d[key] = val.strip()
result.append(d)

Related

How to count words in a list of lists?

I have a list of lists like this: [['Hello', 'Hi'], ["Hola", "Hi", "Ciao"], ["Ciao", "Hi"]].
What I want to do is to create a dictionary where the keys are every word from my list of lists and the values are the word count of words that appear only in the small lists where my key appeared.
Desired output:
dict = {'Hello': {'Hi':1}, 'Hi': {'Hello':1, 'Hola':1, 'Ciao':2},
'Hola':{'Hi':1, 'Ciao':1}, 'Ciao':{'Hola':1, 'Hi':2}}
Note: I know how to use Python and how to deal with data structures, but I am struggling with
the algorithm. I mean how many loops should I have and what my conditions should be?
Consider just one of your lists: ['Hello', 'Hi']. This produces two "pairs" in your output (Hi -> Hello) and (Hello -> Hi). To process one of the lists we're looking at something like:
for x in l:
for y in l:
if x != y:
[update the count of x -> y]
(You could use itertools.combinations or itertools.permutations (depending on preference) to turn this into one loop.)
So how should we store the counts? As noted, the inner dictionaries are calling out to be instances of Counter, since it's basically a dictionary which defaults to 0 if the key is missing (meaning you don't have to check for the presence of the key, you can just increment the value). It would be convenient if your outer dictionary could be a dictionary that defaults to an empty Counter, which you can accomplish with defaultdict.
I'll leave it to you to write the code to update the counts and process all the lists, but hopefully this is enough to put you on the right path. (Both defaultdict and Counter are in collections. I initially found the defaultdict documentation kind of confusion--you'd create one with counts = defaultdict(Counter).)

Inquiry on dictionary comprehension

The following code is a bit from a bigger piece. lines is a 2D list and keyss is a 1D list. All element in lines is the same length as keyss.
datadict = []
for element in lines:
for index in range(len(element)):
datadict.append({keyss[index]: element[index]})
I was wondering if there was a way of writing this using dictionary comprehension? This is more of a curious question as the shown code works just fine for what I'm doing. I've been trying and couldn't find a way too. If you can could go over the syntax of how it would look a bit as well, Thanks!
EDIT#1:
Reading through the responses, I realized it wasn't really working. I'm trying to do a list comprehension where every element is a dictionary comprehension. I'm not entirely sure if that is possible or not. I want to make a list of dictionaries where I take every element in keyss and match index for index in a element in lines which is a list, if that makes sense.
EDIT #2:
I found data_list = [{keyss[i]:row[i] for i in range(len(keyss))} for row in lines] to work.
A dictionary comprehension creates a dictionary. You want a list comprehension:
datalist = [{keyss[index]:element[index]}) for element in lines
for index in range(len(element))]
You can find the documentation on the syntax here.
Your current code doesn't create a dictionary, but if that was your intent, this can be accomplished by
dict(zip(keyss, elements))
or the dictionary comprehension
{key: value for key, value in zip(keyss, elements)}
As mentioned by eugene, it will be list comprehension and not dict comprehension. You may further simplify the code by using zip() as you need the from element and keyss list corresponding to same index. Hence, your simplified list comprehension expression should be as:
datalist = [{k: e} for elements in lines for e, k in zip(elements, keyss)]

What's the fastest way to identify the 'name' of a dictionary that contains a specific key-value pair?

I'd like to identify the dictionary within the following list that contains the key-value pair 'Keya':'123a', which is ID1 in this case.
lst = {ID1:{'Keya':'123a','Keyb':456,'Keyc':789},ID2:{'Keya':'132a','Keyb':654,'Keyc':987},ID3:{'Keya':'5433a','Keyb':222,'Keyc':333},ID4:{'Keya':'444a','Keyb':777,'Keyc':666}}
It's safe to assume all dictionaries have the same key's, but have different values.
I currently have the following to identify which dictionary has the value '123a' for the key 'Keya', but is there a shorter and faster way?
DictionaryNames = map(lambda Dict: str(Dict),lst)
Dictionaries = [i[1] for i in lst.items()]
Dictionaries = map(lambda Dict: str(Dict),Dictionaries)
Dict = filter(lambda item:'123a' in item,Dictionaries)
val = DictionaryNames[Dictionaries.index(Dict[0])]
return val
If you actually had a list of dictionaries, this would be:
next(d for d in list_o_dicts if d[key]==value)
Since you actually have a dictionary of dictionaries, and you want the key associated with the dictionary, it's:
next(k for k, d in dict_o_dicts.items() if d[key]==value)
This returns the first matching value. If you're absolutely sure there is exactly one, or if you don't care which you get if there are more than one, and if you're happy with a StopIteration exception if you were wrong and there isn't one, that's exactly what you want.
If you need all matching values, just do the same with a list comprehension:
[k for k, d in dict_o_dicts.items() if d[key]==value]
That list can of course have 0, 1, or 17 values.
You can just do [name for name, d in lst.iteritems() if d['Keya']=='123a'] to get a list of all the dictionaries in lst that have that value for that key. If you know there is only one, you can get it with [name for name, d in lst.iteritems() if d['Keya']=='123a'][0]. (As Andy mentions in a comment, your name lst is misleading, since lst is actually a dictionary of dictionaries, not a list.)
Since you want the fastest, you should short-cut your search as soon as you find the data you are after. Iterating through the whole list is not necessary, nor is producing any temporary dictionary:
for key,data in lst.iteritems():
if data['Keya']=='132a':
return key #or break is not in a function
Å different way to do this is to use the appropriate data structure: Keep a "reverse map" of key-value pairs to names. If your dictionary of dictionaries is static after being built, you can build the reverse dictionary like this:
revdict = {(key, value): name
for name, subdict in dictodicts.items()
for key, value in subdict.items()}
If not, you just need to add revdict[key, value] = name for each d[name][key] = value statement and build them up in parallel.
Either way, to find the name of the dict that maps key to value, it's just:
revdict[key, value]
For (a whole lot) more information (than you actually want), and some sample code for wrapping things up in different ways… I dug up an unfinished blog post, considered editing it, and decided to not bother and just clicked Publish instead, so: Reverse dictionary lookup and more, on beyond z.

Uniquifying a list of lists in python

Up until now I have been using this code to uniquify (remove duplicates) from list in python:
my_list = list(set(my_list))
I now have a list of lists, I want to be able to remove duplicates from within the list of lists. For example:
(['possible-duplicate', 'random-data'], ['possible-duplicate', 'random-data'], ['possible-duplicate', 'random-data'])
I want to remove the whole sublist if possible-duplicate is a duplicate.
Can this be done?
Thanks
seen = set()
[sublist for sublist in my_list if sublist[0] not in seen and not seen.add(sublist[0])]
This happens to preserve order as well, which list(set(...)) does not.
Make a dictionary from your data:
data = (['possible-duplicate', '12345'],
['not-a-duplicate', '54321'],
['possible-duplicate', '51423'])
data_unique = dict(data)
Result is {'not-a-duplicate': '54321', 'possible-duplicate': '51423'}, or if you prefer a list of tuples, use date_unique.items(), which gives you [('not-a-duplicate', '54321'), ('possible-duplicate', '51423')].
Or for the more general case, where the sublists have more than two elements, you can use this
data_unique = dict((d[0], d) for d in data)
and then use data_unique.values() to reclaim the "uniquified" list.

A way to guarantee ordering of key/value list from unordered dictionary?

I have a dictionary, which contains a title and the data. Is there a way to split this data into two lists while keeping the order it was extracted from the dictionary? I have to process the key list and the value list separately, and then I use those lists to build a string.
It's important because I print them out separately, and the output has to match. It doesn't matter if lists are out of order than when they were entered. So long as their positions match in the lists, it's fine.
Here is a very simple example to represent the case:
mydict = {'Hello':1, 'World':2, 'Again':3}
keys = mydict.keys()
values = mydict.values()
print 'The list of keys are: %s' % stringify(keys)
print 'The corresponding values are: %s' % stringify(values)
# Output:
> The list of keys are: Hello, Again, World
> The corresponding values are: 1, 3, 2
I know I can build an ordered dictionary and then getting the key/value ordering will be guaranteed, but I would also like to handle this case as well (non-ordered dictionary).
Even though the order you see the pairs in is arbitrary, the output from keys() and values() will always align, assuming you don't modify the dictionary. From the docs:
If items(), keys(), values(), iteritems(), iterkeys(), and
itervalues() are called with no intervening modifications to the
dictionary, the lists will directly correspond. This allows the
creation of (value, key) pairs using zip(): pairs = zip(d.values(),
d.keys()). The same relationship holds for the iterkeys() and
itervalues() methods: pairs = zip(d.itervalues(), d.iterkeys())
provides the same value for pairs. Another way to create the same list
is pairs = [(v, k) for (k, v) in d.iteritems()].
titles = myDict.keys()
allData = [myDict[t] for t in titles]
This way, titles might be in some unpredictable order, but each element in allData will be the data pertaining to the corresponding element in titles
Just use items, which gives you, effectively, a zipped-together copy of keys and values:
items = mydict.items()
print 'The list of keys are: %s' % stringify([key for key, value in items])
print 'The list of values are: %s' % stringify([value for key, value in items])
Just don't mutate the dict and you'll be fine. Otherwise, there's just a twist on what you've done already of:
keys, values = zip(*mydict.items())
Which somehow feels "safer" than two operations...

Categories

Resources