White Wolf
White Wolf

Reputation: 27

Adding list of values to a list of dict

I have two list, one list containing dictionaries, the other list values.

l_dic = [
  {
    'a': 5,
    'b': 7,
    'c': [1,2,3,4,5]
  },
  {
    'a': 12,
    'b': 4,
    'c': [1,2,3,4,5]
  }
]

val = [458,646]

Now I'm trying to add the values to the dictionaries, so the result is looking like this:

res_dic = [
  {
    'a': 5,
    'b': 7,
    'c': [1,2,3,4,5],
    'd': 458
  },
  {
    'a': 12,
    'b': 4,
    'c': [1,2,3,4,5],
    'd': 646
  }
]

How can I achieve this?

Upvotes: 2

Views: 107

Answers (4)

Nizam
Nizam

Reputation: 400

You can try the map function which takes a function and an iterable as arguments and applies the function to each element in the iterable parallelly utilizing all the cores on your machine

l_dic = [
  {
    'a': 5,
    'b': 7,
    'c': [1,2,3,4,5]
  },
  {
    'a': 12,
    'b': 4,
    'c': [1,2,3,4,5]
  }
]

val = [458,646]

def assign(x):
  l_dic[x]['d'] = val[x]

#runs paralelly utilizing all cores on your machine
ignore_this = [*map(lambda x: assign(x),range(len(l_dic)))]

Output

l_dic

{'a': 5, 'b': 7, 'c': [1, 2, 3, 4, 5], 'd': 458},
 {'a': 12, 'b': 4, 'c': [1, 2, 3, 4, 5], 'd': 646}]

Upvotes: 0

kederrac
kederrac

Reputation: 17322

you can use python built-in function zip with list comprehension

l_dic = [{**d, 'd': e} for d, e in zip(l_dic, val)]

output:

[
  {
    "a": 5,
    "b": 7,
    "c": [1, 2, 3, 4, 5],
    "d": 458
  },
  {
    "a": 12,
    "b": 4,
    "c": [1, 2, 3, 4, 5],
    "d": 646
  }
]

or you can use a for loop:

for d, v in zip(l_dic, val):
    d['d'] = v

here is a benchmark of the proposed solutions:

from simple_benchmark import BenchmarkBuilder
b = BenchmarkBuilder()



@b.add_function()
def kederrac_for_loop(args):
    l_dic, val = args
    for d, v in zip(l_dic, val):
        d['d'] = v


@b.add_function()
def kederrac_list_comprehension(args):
    l_dic, val = args
    l_dic = [{**d, 'd': e} for d, e in zip(l_dic, val)]

@b.add_function()
def GoodDeeds_for_loop(args):
    l_dic, val = args
    for i in range(len(val)):
        l_dic[i]['d'] = val[i]

@b.add_function()        
def Nizam_solution(args)    : 
    l_dic, val = args
    def assign(x):
        l_dic[x]['d'] = val[x]

    #runs paralelly utilizing all cores on your machine
    ignore_this = [*map(lambda x: assign(x),range(len(l_dic)))]

@b.add_arguments('Number of elements')
def argument_provider():
    for exp in range(2, 16):
        size = 2**exp
        l_dic = [{i : choice(range(100)) for i in range(choice(range(3, 100)))} for _ in range(size)]
        val = list(range(size))

        yield size, (l_dic, val)

r = b.run()
r.plot()

output:

enter image description here

as you can see the for loop solution is the fastest one

Upvotes: 2

David Culbreth
David Culbreth

Reputation: 2776

This problem is a little undefined, since the exact pattern of your keys isn't really defined beyond 26 items, but with some assumptions, you can work with it. What we'll do is zip() your list of dictionaries and your list of items, and do the assignment on a line-by-line basis.

def dict_list_apply(dict_list:list, items_list:list):

  def get_next_key(_dict):
    ab = "abcdefghijklmnopqrstuvwxyz"
    return ab[len(_dict)%len(ab)] * (len(_dict)//len(ab)+1)

  for _dict, _item in zip(dict_list, items_list):
    _dict[get_next_key(_dict)] = _item

The above code will insert items with keys in the following pattern:

a, b, ..., y, z, aa, bb, ..., yy, zz, aaa, bbb, ..., etc.

This means that we can indefinitely continue to add keys to each dictionary, regardless of the length of the other dictionaries.

Then, if we run something like this:

l_dic = [
  {
    'a': 5,
    'b': 7,
    'c': [1,2,3,4,5]
  },
  {
    'a': 12,
    'b': 4,
    'c': [1,2,3,4,5]
  }
]

val = [458,646]

for x in range(100):
    dict_list_apply(l_dic, map(lambda v: v + x, val))
pprint.pprint(l_dic)

Then we get the following output:

[{'a': 5,
  'aa': 481,
  'aaa': 507,
  'aaaa': 533,
  'b': 7,
  'bb': 482,
  'bbb': 508,
  'bbbb': 534,
  'c': [1, 2, 3, 4, 5],
  'cc': 483,
  'ccc': 509,
  'cccc': 535,
  'd': 458,
  'dd': 484,
  'ddd': 510,
  'dddd': 536,
  'e': 459,
  'ee': 485,
  'eee': 511,
  'eeee': 537,
  'f': 460,
  'ff': 486,
  'fff': 512,
  'ffff': 538,
  'g': 461,
  'gg': 487,
  'ggg': 513,
  'gggg': 539,
  'h': 462,
  'hh': 488,
  'hhh': 514,
  'hhhh': 540,
  'i': 463,
  'ii': 489,
  'iii': 515,
  'iiii': 541,
  'j': 464,
  'jj': 490,
  'jjj': 516,
  'jjjj': 542,
  'k': 465,
  'kk': 491,
  'kkk': 517,
  'kkkk': 543,
  'l': 466,
  'll': 492,
  'lll': 518,
  'llll': 544,
  'm': 467,
  'mm': 493,
  'mmm': 519,
  'mmmm': 545,
  'n': 468,
  'nn': 494,
  'nnn': 520,
  'nnnn': 546,
  'o': 469,
  'oo': 495,
  'ooo': 521,
  'oooo': 547,
  'p': 470,
  'pp': 496,
  'ppp': 522,
  'pppp': 548,
  'q': 471,
  'qq': 497,
  'qqq': 523,
  'qqqq': 549,
  'r': 472,
  'rr': 498,
  'rrr': 524,
  'rrrr': 550,
  's': 473,
  'ss': 499,
  'sss': 525,
  'ssss': 551,
  't': 474,
  'tt': 500,
  'ttt': 526,
  'tttt': 552,
  'u': 475,
  'uu': 501,
  'uuu': 527,
  'uuuu': 553,
  'v': 476,
  'vv': 502,
  'vvv': 528,
  'vvvv': 554,
  'w': 477,
  'ww': 503,
  'www': 529,
  'wwww': 555,
  'x': 478,
  'xx': 504,
  'xxx': 530,
  'xxxx': 556,
  'y': 479,
  'yy': 505,
  'yyy': 531,
  'yyyy': 557,
  'z': 480,
  'zz': 506,
  'zzz': 532},
 {'a': 12,
  'aa': 669,
  'aaa': 695,
  'aaaa': 721,
  'b': 4,
  'bb': 670,
  'bbb': 696,
  'bbbb': 722,
  'c': [1, 2, 3, 4, 5],
  'cc': 671,
  'ccc': 697,
  'cccc': 723,
  'd': 646,
  'dd': 672,
  'ddd': 698,
  'dddd': 724,
  'e': 647,
  'ee': 673,
  'eee': 699,
  'eeee': 725,
  'f': 648,
  'ff': 674,
  'fff': 700,
  'ffff': 726,
  'g': 649,
  'gg': 675,
  'ggg': 701,
  'gggg': 727,
  'h': 650,
  'hh': 676,
  'hhh': 702,
  'hhhh': 728,
  'i': 651,
  'ii': 677,
  'iii': 703,
  'iiii': 729,
  'j': 652,
  'jj': 678,
  'jjj': 704,
  'jjjj': 730,
  'k': 653,
  'kk': 679,
  'kkk': 705,
  'kkkk': 731,
  'l': 654,
  'll': 680,
  'lll': 706,
  'llll': 732,
  'm': 655,
  'mm': 681,
  'mmm': 707,
  'mmmm': 733,
  'n': 656,
  'nn': 682,
  'nnn': 708,
  'nnnn': 734,
  'o': 657,
  'oo': 683,
  'ooo': 709,
  'oooo': 735,
  'p': 658,
  'pp': 684,
  'ppp': 710,
  'pppp': 736,
  'q': 659,
  'qq': 685,
  'qqq': 711,
  'qqqq': 737,
  'r': 660,
  'rr': 686,
  'rrr': 712,
  'rrrr': 738,
  's': 661,
  'ss': 687,
  'sss': 713,
  'ssss': 739,
  't': 662,
  'tt': 688,
  'ttt': 714,
  'tttt': 740,
  'u': 663,
  'uu': 689,
  'uuu': 715,
  'uuuu': 741,
  'v': 664,
  'vv': 690,
  'vvv': 716,
  'vvvv': 742,
  'w': 665,
  'ww': 691,
  'www': 717,
  'wwww': 743,
  'x': 666,
  'xx': 692,
  'xxx': 718,
  'xxxx': 744,
  'y': 667,
  'yy': 693,
  'yyy': 719,
  'yyyy': 745,
  'z': 668,
  'zz': 694,
  'zzz': 720}]

Now, this isn't the only way to generate keys, so you can change that by modifying the get_next_key function to provide the pattern that you want.

Upvotes: 0

GoodDeeds
GoodDeeds

Reputation: 8507

You can just use a loop:

for i in range(len(val)):
    res_dic[i]['d'] = val[i]

assuming res_dic and val are lists of the same length.

Upvotes: 1

Related Questions