aabujamra
aabujamra

Reputation: 4636

Function with dictionaries as optional arguments - Python

I'm trying to create a function that might receive as input many or a few dictionaries. I'm using the following code:

def merge_many_dics(dic1,dic2,dic3=True,dic4=True,dic5=True,dic6=True,dic7=True,dic8=True,dic9=True,dic10=True):
"""
Merging up to 10 dictionaries with same keys and different values
:return: a dictionary containing the common dates as keys and both values as values
"""
manydics = {}
for k in dic1.viewkeys() & dic2.viewkeys() & dic3.viewkeys() & dic4.viewkeys() & dic5.viewkeys() & dic6.viewkeys()\
        & dic7.viewkeys() & dic8.viewkeys() & dic9.viewkeys() & dic10.viewkeys():
    manydics[k] = (dic1[k], dic2[k],dic3[k],dic4[k],dic5[k],dic6[k],dic7[k],dic8[k],dic9[k],dic10[k])

return manydics

Note that I'm trying to equal the arguments dic3, dic4, dic5 and so on to "True", so when they are not specified and are called in the function nothing happens. However I'm getting the following error:

Traceback (most recent call last):
File "/Users/File.py", line 616, in <module>
main_dic=merge_many_dics(dic1,dic2,dic3,dic4)
File "/Users/File.py", line 132, in merge_many_dics
& dic7.viewkeys() & dic8.viewkeys() & dic9.viewkeys() & dic10.viewkeys():
AttributeError: 'bool' object has no attribute 'viewkeys'

Anyone to enlight my journey available?

Upvotes: 11

Views: 7077

Answers (5)

byrass
byrass

Reputation: 360

As the error says, you cannot view the keys of a boolean, aka, True.viewkeys() does not work. Change your default dictionary's to be empty, leaving:

def merge_many_dics(dic1,dic2,dic3={},dic4={},dic5={},dic6={},dic7={},dic8={},dic9={},dic10={}):
    """
    Merging up to 10 dictionaries with same keys and different values
    :return: a dictionary containing the common dates as keys and both values as values
    """
    manydics = {}
    for k in dic1.viewkeys() & dic2.viewkeys() & dic3.viewkeys() & dic4.viewkeys() & dic5.viewkeys() & dic6.viewkeys()\
            & dic7.viewkeys() & dic8.viewkeys() & dic9.viewkeys() & dic10.viewkeys():
        manydics[k] = (dic1[k], dic2[k],dic3[k],dic4[k],dic5[k],dic6[k],dic7[k],dic8[k],dic9[k],dic10[k])

    return manydics

Here is an implementation in which you create a list for every key and add each item, I'm sure it can be optimized a lot more, but it's very readable:

def merge_many_dicts(*args):
    """
    Merging all dictionaries suposing all dictionaries share keys
    :return: a dictionary containing the common dates as keys and both values as values
    """
    manydicts = {}
    for k in args:
        for key in k.iterkeys():
            manydicts[key] = []
    for k in args:
        for key, value in k.iteritems():
            manydicts[key].append(value)

    return manydicts

Upvotes: 0

Sede
Sede

Reputation: 61253

Here is Python 3.x answer based on @falsetru answer and using the operator.and_ function.

>>> from functools import reduce
>>> import operator
>>> def merge_many_dicts(*dicts):
...     common_keys = reduce(operator.and_, (d.keys() for d in dicts))
...     return {key: tuple(d[key] for d in dicts) for key in common_keys}
... 
>>> merge_many_dicts({1:2}, {1:3}, {1:4, 2:5})
{1: (2, 3, 4)}

Upvotes: 4

Randrian
Randrian

Reputation: 1085

You should try the args syntax:

def merge_many_dics(*args):
   iterate over your args to join them

then you can call the function with as many arguments as you like.

A function with *args could be as following:

   def print_all(name, *args):
      print "Hello", name, "here are your args"
      for arg in args:
         print arg

   print_all("Claus", "car", "boat", "house")

this will print:

Hello Clause here are your args

car
boat
house

Upvotes: 6

Youan Wang
Youan Wang

Reputation: 94

You can use the following code, to initial those parameters with in the function

def merge_many_dics(dic1, dic2, dic3=None, dic4=None, dic5=None, dic6=None, dic7=None, dic8=None, dic9=None,
                    dic10=None):
    """
    Merging up to 10 dictionaries with same keys and different values
    :return: a dictionary containing the common dates as keys and both values as values
    """
    for item in locals().items():
        if item is None:
            item = dic1

    manydics = {}
    for k in dic1.viewkeys() & dic2.viewkeys() & dic3.viewkeys() & dic4.viewkeys() & dic5.viewkeys() & dic6.viewkeys() \
            & dic7.viewkeys() & dic8.viewkeys() & dic9.viewkeys() & dic10.viewkeys():
        manydics[k] = (dic1[k], dic2[k], dic3[k], dic4[k], dic5[k], dic6[k], dic7[k], dic8[k], dic9[k], dic10[k])

    return manydics

Upvotes: 0

falsetru
falsetru

Reputation: 369274

Using arbitrary argument list, the function can be called with an arbitrary number of arguments:

>>> def merge_many_dics(*dicts):
...     common_keys = reduce(lambda a, b: a & b, (d.viewkeys() for d in dicts))
...     return {key: tuple(d[key] for d in dicts) for key in common_keys}
...
>>> merge_many_dics({1:2}, {1:3}, {1:4, 2:5})
{1: (2, 3, 4)}

Upvotes: 13

Related Questions