2

I have two list contain multi dictionary, each dictionary has a list as value, these are my list:

list1 = [{'a':[12,22,61],'b':[21,12,50]},{'c':[10,11,47],'d':[13,20,45],'e':[11,24,42]},{'a':[12,22,61],'b':[21,12,50]}]
list2 = [{'f':[21,23,51],'g':[11,12,44]},{'h':[22,26,68],'i':[12,9,65],'j':[10,12,50]},{'f':[21,23,51],'g':[11,12,44]}]

In my case, i need to merge these list with this rule:

  1. Dictionary from the first list (list1) only can be merged by dictionary from the second list (list2) with the same listing index
  2. After both of these list are merged, each dictionary has to be sorted based on the third number of its value

This is the expected result based on two rule above:

result = [
    {'a':[12,22,61],'f':[21,23,51],'b':[21,12,50],'g':[11,12,44]},
    {'h':[22,26,68],'i':[12,9,65],'j':[10,12,50],'c':[10,11,47],'d':[13,20,45],'e':[11,24,42]},
    {'a':[12,22,61],'f':[21,23,51],'b':[21,12,50],'g':[11,12,44]}
    ]

How can i do that? is it possible to be done in python with inline looping?

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
Faizalprbw
  • 529
  • 1
  • 6
  • 17

4 Answers4

3

Try:

[dict(a, **b) for a,b in zip(list1, list2)]
Abel Tadesse
  • 145
  • 5
2

In one line (if you do not count with the import):

from collections import OrderedDict

[OrderedDict(sorted(dict(d1.items() + d2.items()).items(), key=lambda x: x[1][-1],
                    reverse=True)) for d1, d2 in zip(list1, list2)]

[OrderedDict([('a', [12, 22, 61]),
              ('f', [21, 23, 51]),
              ('b', [21, 12, 50]),
              ('g', [11, 12, 44])]),
 OrderedDict([('h', [22, 26, 68]),
              ('i', [12, 9, 65]),
              ('j', [10, 12, 50]),
              ('c', [10, 11, 47]),
              ('d', [13, 20, 45]),
              ('e', [11, 24, 42])]),
 OrderedDict([('a', [12, 22, 61]),
              ('f', [21, 23, 51]),
              ('b', [21, 12, 50]),
              ('g', [11, 12, 44])])]

This works in Python 2.7.

iled
  • 2,142
  • 3
  • 31
  • 43
  • @Faizalprbw yw! Let me know if there is any part that may require explanation. Also, you may find the related questions very useful, e.g., [this one](http://stackoverflow.com/questions/72899/how-do-i-sort-a-list-of-dictionaries-by-values-of-the-dictionary-in-python). – iled Feb 18 '17 at 06:21
  • Actually, this is the very simple example of my problem, i have big json data contains the same structure as that.. But you're example is working, now i'm trying to understand you're syntax myself, if i'm stuck, i'll ask you.. Thank you very much.. @iled – Faizalprbw Feb 18 '17 at 06:25
  • Sure. Basically there are two major questions here: 1. Merge dictionaries; 2. Sort dictionaries. For the first part, you may find [this post](http://stackoverflow.com/q/38987/3079302) very useful. For the second, see the link in my previous comment. The syntax used to wrap these things is a list comprehension and a [lambda function](http://stackoverflow.com/questions/890128/why-are-python-lambdas-useful/890188#890188). – iled Feb 18 '17 at 06:33
  • Note that this doesn't work for python 3 and the result no longer contains dictionaries, and using an `OrderedDict` does not change anything in this case. – Steven Summers Feb 18 '17 at 08:51
  • @StevenSummers Thank you, I had `sorted` and `OrderedDict` in the wrong order. I am not using Python 3, sorry for not specifying that in the first place. – iled Feb 18 '17 at 09:12
0

Dictionaries are not sorted by nature, so if you don't need them sorted your can merge them in a simple one-liner.

result = [ {**d1, **d2} for d1, d2 in zip(list1, list2) ] # python 3.5+

If you are using a lower version then define a merge function.

def merge(d1, d2):
    result = d1.copy()
    result.update(d2)
    return result

And then have

result = [ merge(d1, d2) for d1, d2 in zip(list1, list2) ]

If you do need them sorted then your only option is to use an OrderedDict

from collections import OrderedDict

def merge(d1, d2):
    tempD = d1.copy()
    tempD.update(d2)
    return OrderedDict(sorted(tempD.items(), key = lambda t: t[1][2], reverse = True))

result = [ merge(d1, d2) for d1, d2 in zip(list1, list2) ]

Or even shorter for python 3.5+ is

result = [ OrderedDict(sorted(({**d1, **d2}).items(), key = lambda t: t[1][2], reverse = True)) for d1, d2 in zip(list1, list2) ]
Steven Summers
  • 5,079
  • 2
  • 20
  • 31
-1

You can do like this for your result :

r = map(lambda x,y:dict(x.items() + y.items()), list1, list2)

Result :

[{'a': [12, 22, 61], 'b': [21, 12, 50], 'g': [11, 12, 44], 'f': [21, 23, 51]},
 {'c': [10, 11, 47], 'e': [11, 24, 42], 'd': [13, 20, 45], 'i': [12, 9, 65], 'h': [22, 26, 68], 'j': [10, 12, 50]},
 {'a': [12, 22, 61], 'b': [21, 12, 50], 'g': [11, 12, 44], 'f': [21, 23, 51]}]
Sid Mhatre
  • 3,272
  • 1
  • 19
  • 38