How to merge two lists by index - python

I have two lists:
i = ['a', 'b', 'c']
x = [1,2,3]
i need to produce such dictionary:
xxx = { 'a': [a, 1],
'b': [b, 2],
'c': [c, 3]}
I have done this:
for indx in i:
for indx2 in x:
xxx.update({indx: [indx, indx2]})
but obvioulsy it doesnt work

Using dict comprehension:
>>> i = ['a', 'b', 'c']
>>> x = [1,2,3]
>>> {key: [key, value] for key, value in zip(i, x)}
{'a': ['a', 1], 'c': ['c', 3], 'b': ['b', 2]}

how about this, if tuple can be the value of your dict.
i= ['a', 'b', 'c']
x= [1, 2, 3]
dict(zip(i,zip(i,x)))
{'a': ('a', 1), 'b': ('b', 2), 'c': ('c', 3)}

Related

Count every instance of an item in a list of lists and sum them

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))

How to merge two dictionaries in a specific way?

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]]}

Merging sublists into a list based on sublist item in python

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)

How to flatten the list matrix (list of lists) in order of index?

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]}

How to convert a dictionary into a flat list?

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)

Categories