Python dictionary manipulation - python

I got a list of object
lst = [1,2,3]
I want them in a dictionary with a default key 'number', and then put them in a list.
The result should look like
lst = [{'number':1},{'number':2},{'number':3}
Use less code, please.

Use a list comprehension
lst = [{'number': x} for x in lst]

This matches your code samples:
>>> lst = [1,2,3]
>>> newlst = [dict(number=n) for n in lst]
>>> newlst
[{'number': 1}, {'number': 2}, {'number': 3}]
>>>
What you say, however, is a bit different - you want them all in the same dictionary, or each in a dictionary of its own? The snippet above gives you the latter.

Related

combine two python lists of dict with index

I want to merge two lists into a nested construct.
List_A: [{'id':1,'val':'abc'},{'id':2,'val':'bcd'},{'id':3,'val':'efg'}]
List_B: [{'ref':1,'name':'xyz'},{'ref':2,'name':'opq'},{'ref:2,'name':'jkl'},{'ref':3,'name':'nmo'}]
Result should be:
List_C: [{'id':1,'list_b':[{'name':'xyz'}]},{'id':2,'list_b':[{'name':'opq'},{'name':'jkl'}]},{'id':3,'list_b':[{'name':'nmo'}]}]
I tried pandas join and merge but got no result. Sure, I could iterate through the list and do it key by key, but there might be a much better solution.
Based on your desired output, you don't need List_A at all.
from collections import defaultdict
b = [{'ref':1,'name':'xyz'}, {'ref':2,'name':'opq'}, {'ref':2,'name':'jkl'},{'ref':3,'name':'nmo'}]
dct = {}
[dct.setdefault(tuple(i), list()).append(j) for *i, j in [tuple(x.values()) for x in b]]
[{'id':k[0], 'list_b':list({'name': n} for n in v)} for k, v in dct.items()]
Output:
[{'id': 1, 'list_b': [{'name': 'xyz'}]},
{'id': 2, 'list_b': [{'name': 'opq'}, {'name': 'jkl'}]},
{'id': 3, 'list_b': [{'name': 'nmo'}]}]
Overall this seems like an over-complicated way to store the data, but if you need that specific format (ex for an input to another program) then w/e.
from copy import deepcopy
List_C = deepcopy(List_A)
for dct1 in List_C:
dct1.pop('val')
dct1['list_b'] = list()
for dct2 in List_B:
if dct1['id'] == dct2['ref']:
dct3 = dct2.copy()
dct3.pop('ref')
dct1['list_b'].append(dct3)

Count occurrence of strings in list of lists

I want to count the number of times a string has occurred in a list which is in another list and store it in a list of dictionary where each dictionary has count of a list.
Ex,
list = [['Sam','John','Alex','Sam','Alex'],['Max','Sam','Max']...]
and I want my list of dictionaries to be like:
count_list = [{'Sam':2,'Alex':2,'John':1}, {'Max':2, 'Sam':1}..]
I am iterating through each list to count number of times each string has occurred and adding each result to dict. But I end up having different result every time and not the correct values.
count_list = []
for l in list :
d = {}
for str in l:
if str not in d:
d[str] = l.count(str)
count_list.append(d)
Any help would be useful.Thanks.
It would be easier to use collections.Counter() here:
>>> from collections import Counter
>>> lst = [["Sam", "John", "Alex", "Sam", "Alex"], ["Max", "Sam", "Max"]]
>>> list(map(Counter, lst))
[Counter({'Sam': 2, 'Alex': 2, 'John': 1}), Counter({'Max': 2, 'Sam': 1})]
You could also use a list comprehension instead of using map() if thats easier to understand:
>>> [Counter(l) for l in lst]
[Counter({'Sam': 2, 'Alex': 2, 'John': 1}), Counter({'Max': 2, 'Sam': 1})]
Note: Counter is a subclass of dict, so you can treat them like normal dictionaries.
You can always cast to dict() if you want to as well:
>>> [dict(Counter(l)) for l in lst]
[{'Sam': 2, 'John': 1, 'Alex': 2}, {'Max': 2, 'Sam': 1}]
You should also not use list as a variable name, since it shadows the builtin function list().
Currently, you are doing the following:
count_list = []
for l in list :
d = {}
for str in l:
if str not in d:
d[str] = l.count(str)
count_list.append(d)
Note that you are appending the dictionary for each string in the sub lists, rather than one dictionary per sub list.
Doing the following should address the issue:
count_list = []
for l in list :
d = {}
for str in l:
if str not in d:
d[str] = l.count(str)
count_list.append(d)

How to create a dictionary out of a list of lists in python?

Let's suppose I have the following list made out of lists
list1 = [['a','b'],['a'],['b','c'],['c','d'],['b'], ['a','d']]
I am wondering if there is a way to convert every element of list1 in a dictionary where all the new dictionaries will use the same key. E.g: if ['a']
gets to be {'a':1}, and ['b'] gets to be {'b':2}, I would like for all keys a the value of 1 and for all keys b the value of 2. Therefore, when creating the dictionary of ['a','b'], I would like to turn into {'a':1, 'b':2}.
What I have found so far are ways to create a dictionary out of lists of lists but using the first element as the key and the rest of the list as the value:
Please note that's not what I am interested in.
The result I would want to obtain from list1 is something like:
dict_list1 = [{'a':1,'b':2}, {'a':1}, {'b':2,'c':3}, {'c':3,'d':4}, {'b':2}, {'a':1,'d':4}]
I am not that interested in the items being that numbers but in the numbers being the same for each different key.
You need to declare your mapping first:
mapping = dict(a=1, b=2, c=3, d=4)
Then, you can just use dict comprehension:
[{e: mapping[e] for e in li} for li in list1]
# [{'a': 1, 'b': 2}, {'a': 1}, {'b': 2, 'c': 3}, {'c': 3, 'd': 4}, {'b': 2}, {'a': 1, 'd': 4}]
Using chain and OrderedDict you can do auto mapping
from itertools import chain
from collections import OrderedDict
list1 = [['a','b'],['a'],['b','c'],['c','d'],['b'], ['a','d']]
# do flat list for auto index
flat_list = list(chain(*list1))
# remove duplicates
flat_list = list(OrderedDict.fromkeys(flat_list))
mapping = {x:flat_list.index(x)+1 for x in set(flat_list)}
[{e: mapping[e] for e in li} for li in list1]
Here a try with ord() also it will work for both capital and lower letters :
[{e: ord(e)%32 for e in li} for li in list1]

Turn a list of string to dictionary in Python

I have a list of strings like this:
l = ['ABC, Apple, 20021015, 20030102', 'CDE, Graps, 20020506, 20030130']
I want to convert this list to a dictionary like
d = { 'ABC': 'Apple', 'CDE': 'Graps' }
So the key would be the first name in the string and the value would be the second name in the string.
This works in Python 2:
d = {j[0]:j[1] for j in [i.split(', ') for i in l]}
Output:
{'CDE': 'Graps', 'ABC': 'Apple'}
You could do it like this:
for index in range(len(l)):
line = l[index].split(", ")
d[line[0]] = line[1]
So, you split each entry by commas to get each name and date individually, and then you can add them each to the dict as normal.
Alternative, shorter form:
>>> dict(x.split(', ')[:2] for x in l)
{'ABC': 'Apple', 'CDE': 'Graps'}
This works by passing a sequence of two-element lists to dict() which then initializes the dictionary based on that sequence. The sequence being passed is this:
>>> [x.split(', ')[:2] for x in l]
[['ABC', 'Apple'], ['CDE', 'Graps']]

Dictionary comprehension to build list of lists: referencing the current value for a key during comprehension

I am trying to create a list of lists based on hashes. That is, I want a list of lists of items that hash the same. Is this possible in a single-line comprehension?
Here is the simple code that works without comprehensions:
def list_of_lists(items):
items_by_hash = defaultdict(list)
for item in items:
words_by_key[hash(item)].append(item)
return words_by_key.values()
For example, let's say we have this simple hash function:
def hash(string):
import __builtin__
return __builtin__.hash(string) % 10
Then,
>>> l = ['sam', 'nick', 'nathan', 'mike']
>>> [hash(x) for x in l]
[4, 3, 2, 2]
>>>
>>> list_of_lists(l)
[['nathan', 'mike'], ['nick'], ['sam']]
Is there any way I could do this in a comprehension? I need to be able to reference the dictionary I'm building mid-comprehension, in order to append the next item to the list-value.
This is the best I've got, but it doesn't work:
>>> { hash(word) : [word] for word in l }.values()
[['mike'], ['nick'], ['sam']]
It obviously creates a new list every time which is not what I want. I want something like
{ hash(word) : __this__[hash(word)] + [word] for word in l }.values()
or
>>> dict([ (hash(word), word) for word in l ])
{2: 'mike', 3: 'nick', 4: 'sam'}
but this causes the same problem.
[[y[1] for y in x[1]] for x in itertools.groupby(sorted((hash(y), y)
for y in items), operator.itemgetter(0))]

Categories