Related
In Python 3.x, I have a list of lists:
[['a','b','c'], ['a', 'c'], ['c', 'd'] ]
I saw this answer, but it only applies to a single list. How would I do this for a list of lists? My desired output would be a sorted list (or a sortable list) of the frequency of a particular item in a list.
Something like:
{a: 2, b: 1, c: 3, d: 1 }
You could use itertools.chain(*l) as an input to the Counter.
>>> l= [['a','b','c'], ['a', 'c'], ['c', 'd'] ]
>>> Counter(itertools.chain(*l))
Counter({'c': 3, 'a': 2, 'b': 1, 'd': 1})
This may be solved using Counter. Counter creates a dictionary of the counts of the elements in the lists.
L = [['a','b','c'], ['a', 'c'], ['c', 'd'] ]
>>> from collections import Counter
>>> d = Counter()
>>> for sub in L:
d.update(sub)
>>> d
Counter({'c': 3, 'a': 2, 'b': 1, 'd': 1})
You can use Counter from collections to do this very efficiently:
In [161]: from collections import Counter
...:
...: count = Counter()
...:
...: lists = [['a','b','c'], ['a', 'c'], ['c', 'd']]
...:
...: for sublist in lists:
...: count += Counter(sublist)
...:
...: print(count)
Counter({'c': 3, 'a': 2, 'b': 1, 'd': 1})
This is "one-line-able" using python's builtin sum:
In [163]: from collections import Counter
...: lists = [['a','b','c'], ['a', 'c'], ['c', 'd']]
...:
...: count = sum(map(Counter, lists), start=Counter())
...:
...: print(count)
Counter({'c': 3, 'a': 2, 'b': 1, 'd': 1})
You can flatten the list and use Counter. If your list is arbitrarily nested.
from collections import Counter
def flatten(lst):
if not isinstance(lst,list):
return [lst]
else:
return [j for i in lst for j in flatten(i)]
print(Counter(flatten([['a','b','c'], ['a', 'c'], ['c', 'd'] ])))
#Counter({'c': 3, 'a': 2, 'b': 1, 'd': 1})
You can do by itering in each sublist:
dict={}
for sublist in list:
for item in sublist:
if item in dict.keys():
dict[item] +=1
else:
dict[item] =1
you can flatten your list and apply collections.Counter:
from collections import Counter
l = [['a','b','c'], ['a', 'c'], ['c', 'd'] ]
Counter((e for i in l for e in i))
I have a two dictionaries like:
d1 = {'new_list1':['a', 'b', 'c', 'd'], 'new_list2':['a', 'b', 'd', 'e']}
d2 = {'new_list1': [1,2,3,4], 'new_list2': [1,2,4,5]}
I want output like:
d3 = {'new_list1':[['a',1],['b',2],['c',3],['d',4]], 'new_list2':[['a',1],['b',2],['d',4],['e',5]]}
Points to See:
1. both the dictionaries will have same number of keys
2. values present in form of list can have different length, so padding as 0 will be required in case of mismatch
Try this :
d3 = dict(zip(d1.keys(),[list(zip(d1[k], d2[k])) for k in d1]))
Output :
{'new_list1': [('a', 1), ('b', 2), ('c', 3), ('d', 4)], 'new_list2': [('a', 1), ('b', 2), ('d', 4), ('e', 5)]}
If possible match each value between both lists of dictionaries use:
out = {k:list(map(list, zip(v, d2[k]))) for k, v in d1.items()}
print (out)
{'new_list1': [['a', 1], ['b', 2], ['c', 3], ['d', 4]],
'new_list2': [['a', 1], ['b', 2], ['d', 4], ['e', 5]]}
If lengths not match use zip_longest:
from itertools import zip_longest
d1 = {'new_list1':['a', 'b', 'c', 'd'], 'new_list2':['a', 'b']}
d2 = {'new_list1': [1,2,3], 'new_list2': [1,2,4,5]}
out = {k:list(map(list, zip_longest(v, d2[k], fillvalue=0))) for k, v in d1.items()}
Or:
out = {k: list(map(list, zip_longest(d1[k], d2[k], fillvalue=0))) for k in d1}
print (out)
{'new_list1': [['a', 1], ['b', 2], ['c', 3], ['d', 0]],
'new_list2': [['a', 1], ['b', 2], [0, 4], [0, 5]]}
An update to #jezrael answer. I don't think there is any need to typecast the result of map to a list.
from itertools import zip_longest
d1 = {'new_list1':['a', 'b', 'c', 'd'], 'new_list2':['a', 'b']}
d2 = {'new_list1': [1,2,3], 'new_list2': [1,2,4,5]}
out = {k:map(list, zip_longest(v, d2[k], fillvalue=0)) for k, v in d1.items()}
Or:
out = {k: map(list, zip_longest(d1[k], d2[k], fillvalue=0)) for k in d1}
print (out)
{'new_list1': [['a', 1], ['b', 2], ['c', 3], ['d', 0]],
'new_list2': [['a', 1], ['b', 2], [0, 4], [0, 5]]}
Input:
I have this ordered list.
[[1, 'A'], [1, 'B'],[1, 'D'], [2, 'A'],[2,'D'], [3, 'C'], [4, 'D'], [5, 'B'], [6, 'D']]
Desired output
[[1,['A','B','D']],[2, ['A','D']], [3, 'C'], [4, 'D'], [5, 'B'], [6, 'D']]
Since the first item of those two sublists are same.
Also can i convert into a dictionary with a key and those values pair. Like
{1:['A','B','D'],2:['A','D'],3:['C']}
What is the easiest and simplest way to do this?
If the data is ordered, then itertools.groupby is a good approach:
>>> from itertools import groupby
>>> from operator import itemgetter
>>> data = [[1, 'A'], [1, 'B'], [2, 'A'], [3, 'C'], [4, 'D'], [5, 'B'], [6, 'D']]
>>> final_data = []
>>> final_data = []
>>> for k, g in groupby(data, itemgetter(0)):
... group = list(g)
... if len(group) == 1:
... final_data.append(group[0])
... else:
... final_data.append([k, [sub[1] for sub in group]])
...
>>> final_data
[[1, ['A', 'B']], [2, 'A'], [3, 'C'], [4, 'D'], [5, 'B'], [6, 'D']]
>>>
If you want the results in a dictionary, that is even easier:
>>> grouped_dict = {}
>>> for num, letter in data:
... grouped_dict.setdefault(num, []).append(letter)
...
>>> grouped_dict
{1: ['A', 'B'], 2: ['A'], 3: ['C'], 4: ['D'], 5: ['B'], 6: ['D']}
>>>
You can create the dictionary directly from the input.
from collections import defaultdict
input = [[1, 'A'], [1, 'B'],[1, 'D'], [2, 'A'],[2,'D'], [3, 'C'], [4, 'D'], [5, 'B'], [6, 'D']]
d = defaultdict(list)
for el in input: d[el[0]].append(el[1])
The output of d will be:
{1: ['A', 'B', 'D'], 2: ['A', 'D'], 3: ['C'], 4: ['D'], 5: ['B'], 6: ['D']}
If the order is not important, and you want dictionary anyway:
import collections
your_list = [[1,'A'], [1,'B'], [1,'D'], [2,'A'], [2,'D'], [3,'C'], [4,'D'], [5,'B'], [6,'D']]
result = collections.defaultdict(list)
for k, v in your_list:
result[k].append(v)
# {1: ['A', 'B', 'D'], 2: ['A', 'D'], 3: ['C'], 4: ['D'], 5: ['B'], 6: ['D']}
You can also do it without collections.defaultdict (probably at some performance penalty, in dependence of key frequency):
your_list = [[1,'A'], [1,'B'], [1,'D'], [2,'A'], [2,'D'], [3,'C'], [4,'D'], [5,'B'], [6,'D']]
result = {}
for k, v in your_list:
result[k] = result.get(k, []) + [v]
# {1: ['A', 'B', 'D'], 2: ['A', 'D'], 3: ['C'], 4: ['D'], 5: ['B'], 6: ['D']}
You can use groupby from itertools module like this example:
a = [[1, 'A'], [1, 'B'],[1, 'D'], [2, 'A'],[2,'D'], [3, 'C'], [4, 'D'], [5, 'B'], [6, 'D']]
final = []
for k, v in groupby(sorted(a, key=lambda x: x[0]), lambda x: x[0]):
bb = list(v)
if len(bb) > 1:
final.append([k, [j for _, j in bb]])
else:
final.append([k, bb[0][1]])
# OR:
# Within a list comprehension
# final = [[k, [j[1] for j in list(v)]] for k, v in groupby(sorted(a, key=lambda x: x[0]), lambda x: x[0])]
print(final)
Output:
[[1, ['A', 'B', 'D']],
[2, ['A', 'D']],
[3, 'C'],
[4, 'D'],
[5, 'B'],
[6, 'D']]
Then to convert the final list into a dict you can do:
final_dict = {k:v if isinstance(v, list) else [v] for k, v in final}
print(final_dict)
Output:
{1: ['A', 'B', 'D'], 2: ['A', 'D'], 3: ['C'], 4: ['D'], 5: ['B'], 6: ['D']}}
I found better do the opposite, instead of make a list and then a dictionary I made dictionary and then a list.
Input:
in_list = [[1, 'A'], [1, 'B'],[1, 'D'], [2, 'A'],[2,'D'], [3, 'C'], [4, 'D'], [5, 'B'], [6, 'D']]
Code:
mydict = {}
for sublist in in_list:
if sublist[0] in mydict.keys():
mydict[sublist[0]] = [*mydict[sublist[0]],sublist[1]]
else:
mydict[sublist[0]] = sublist[1]
Output:
>>> mydict
{1: ['A', 'B', 'D'], 2: ['A', 'D'], 3: 'C', 4: 'D', 5: 'B', 6: 'D'}
Make an easy list with the dictionary:
mylist = list(mydict.items())
Output:
>>> mylist
[(1, ['A', 'B', 'D']), (2, ['A', 'D']), (3, 'C'), (4, 'D'), (5, 'B'), (6, 'D')]
Make another list with the dictionary:
mylist = = [[k,v] for k,v in mydict.items()]
Same as:
mylist = []
for key, value in mydict.items():
Output:
>>> mylist
[[1, ['A', 'B', 'D']], [2, ['A', 'D']], [3, 'C'], [4, 'D'], [5, 'B'], [6, 'D']]
in_list
out_list = []
sublist = []
i = 0
for l in in_list:
if l[0] != i:
i = l[0]
sublist = []
out_list.append([i, sublist])
sublist.append(l[1])
dico = dict( out_list)
In the python documentation example, https://docs.python.org/2/library/collections.html#defaultdict-examples
they used solved same problems in your post.
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
... d[k].append(v)
...
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
then I voted an answer with defaultdict.
dic = {}
res_lst = []
lst = [[1, 'A'], [1, 'B'],[1, 'D'], [2, 'A'],[2,'D'], [3, 'C'], [4, 'D'], [5, 'B'], [6, 'D']]
convert into list pair
for lst_item in lst:
if lst_item[0] in dic:
for item in lst_item[1:]:
dic[lst_item[0]].append(item)
else:
dic[lst_item[0]] = lst_item[1:]
convert into key value pair
for item in dic:
lst1 = []
lst1.append(item)
if(len(dic[item]) == 1):
lst1.append(dic[item][0])
else:
lst1.append(dic[item])
res_lst.append(lst1)
print(res_lst)
list_data = [['a', 'b', 'c', 'd'],
['hello', 'mellow', 'fellow', 'jello'],
[2, 3, 6, 8]]
flattened = []
for data in list_data:
for x in data:
flattened.append(x)
print(flatenned)
gives me:
['a', 'b', 'c', 'd', 'hello', 'mellow', 'fellow', 'jello', 2, 3, 6, 8]
How, can I rather flatten this lits to (below) in a most simple way:
['a', 'hello', 2, 'b', 'mellow', 3, 'c', 'fellow', 6, 'd', 'jello', 8]
and to dictionary:
['a': ['hello' 2], 'b': ['mellow', 3], 'c': ['fellow', 6], 'd': ['jello', 8]]
Explanation of the process would be helpful.
You can use zip to transpose the matrix:
[y for x in zip(*list_data) for y in x]
# ['a', 'hello', 2, 'b', 'mellow', 3, 'c', 'fellow', 6, 'd', 'jello', 8]
To get the dictionary:
dict(zip(list_data[0], zip(*list_data[1:])))
# {'a': ('hello', 2), 'b': ('mellow', 3), 'c': ('fellow', 6), 'd': ('jello', 8)}
Description:
Dictionary is reported as keys and values, d[k,v].
so, first part list_data[0] picks keys from the first index (0) of every list, and the latter part zip(*list_data[1:]) adds the remaining elements of the list as the values for that key.
For flattening the list, you may use itertools.chain with zip as:
>>> from itertools import chain
>>> list(chain(*zip(*list_data)))
['a', 'hello', 2, 'b', 'mellow', 3, 'c', 'fellow', 6, 'd', 'jello', 8]
For mapping the values to desired dict, you may use zip with dictionary comprehension expression as:
>>> {i: [j, k] for i, j, k in zip(*list_data)}
{'a': ['hello', 2], 'c': ['fellow', 6], 'b': ['mellow', 3], 'd': ['jello', 8]}
Given a Python dict like:
{
'a': 1,
'b': 2,
'c': 3
}
What's an easy way to create a flat list with keys and values in-line? E.g.:
['a', 1, 'b', 2, 'c', 3]
Since you are using Python 2.7, I would recommend using dict.iteritems or dict.viewitems and list comprehension, like this
>>> [item for pair in d.iteritems() for item in pair]
['a', 1, 'c', 3, 'b', 2]
>>> [item for pair in d.viewitems() for item in pair]
['a', 1, 'c', 3, 'b', 2]
dict.iteritems or dict.viewitems is better than dict.items because, they don't create a list of key-value pairs.
If you are wondering how you can write portable code which would be efficient in Python 3.x as well, then you just iterate the keys like this
>>> [item for k in d for item in (k, d[k])]
['a', 1, 'c', 3, 'b', 2]
In [39]: d = {
'a': 1,
'b': 2,
'c': 3
}
In [40]: list(itertools.chain.from_iterable(d.items()))
Out[40]: ['b', 2, 'a', 1, 'c', 3]
Note that dicts are unordered, which means that the order in which you enter keys is not always the order in which they are stored. If you want to preserve order, you might be looking for an ordereddict
You can use sum:
>>> d = {'a': 1, 'b': 2, 'c': 3}
>>> sum(d.items(), tuple())
('a', 1, 'c', 3, 'b', 2)
res_list = []
for k, v in d:
res_list.append(k).append(v)