443,275 Members | 1,745 Online Need help? Post your question and get tips & solutions from a community of 443,275 IT Pros & Developers. It's quick & easy.

# help with addition of dictionary values

 P: 10 hi, i would like to add my two matrices, using __add__ Expand|Select|Wrap|Line Numbers class m:       def __init__(self, mtx={}, m=0, n=0):         self.matrix = {}         self.matrix.update(mtx)         self.row = m         self.col = n       def __getitem__(self, ij):         return self.matrix.get(ij,0)       def __setitem__(self, ij, val):         self.matrix[i,j] = val       def __add__(self, other):         result = m()         for i in other:             self.result[i] = self.matrix.get(i, 0) + other[i]         return result            but i always get an error. Hope you can help me Nov 10 '07 #1
18 Replies

 Expert 5K+ P: 6,596 Use the dictionary method, items(). Like this: Expand|Select|Wrap|Line Numbers >>> dd_1 = {'a':1, 'b':2, 'c':3} >>> dd_2 = {'a':3, 'b':4} >>> dd_res = {} >>> for key, value in dd_1.items(): ...     dd_res[key] = dd_2.get(key, 0) + value ...      >>> dd_res {'a': 4, 'c': 3, 'b': 6} >>>  Nov 10 '07 #2

 P: 10 Use the dictionary method, items. Like this: Expand|Select|Wrap|Line Numbers >>> dd_1 = {'a':1, 'b':2, 'c':3} >>> dd_2 = {'a':3, 'b':4} >>> dd_res = {} >>> for key, value in dd_1.items(): ...     dd_res[key] = dd_2.get(key, 0) + value ...      >>> dd_res {'a': 4, 'c': 3, 'b': 6} >>>  for this loop what does value means here? how can i use the one that i have set in __setitem__? does get(key, 0) gives me the value that i have set in __setitem__? sorry if i sound confusing, but honestly i'm confused with the passing of tuples, i want to know exactly where does each value goes after using the method. am already fine with __init__ method, i'm just confused what happens to the values after setting them for key, value in dd_1.items(): ... dd_res[key] = dd_2.get(key, 0) + value Nov 10 '07 #3

 Expert 5K+ P: 6,596 for this loop what does value means here? how can i use the one that i have set in __setitem__? does get(key, 0) gives me the value that i have set in __setitem__? sorry if i sound confusing, but honestly i'm confused with the passing of tuples, i want to know exactly where does each value goes after using the method. am already fine with __init__ method, i'm just confused what happens to the values after setting them for key, value in dd_1.items(): ... dd_res[key] = dd_2.get(key, 0) + value OK. Your class is coming along nicely. The on-line help can probably explain these things better that I can (more succinctly, anyway): Expand|Select|Wrap|Line Numbers >>> help(dd_1.get) Help on built-in function get:   get(...)     D.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None.   >>> help(dd_1.items) Help on built-in function items:   items(...)     D.items() -> list of D's (key, value) pairs, as 2-tuples But probably the best way to learn what a chunk of code (your own or someone else's) is like this: Expand|Select|Wrap|Line Numbers >>> for key, value in dd_1.items(): ...     print key, value ...     dd_res[key] = dd_2.get(key, 0) + value Nov 10 '07 #4

 Expert 5K+ P: 6,596 If the assignment doesn't allow using a subclass, you'll have to use the tricks below to take this apart and create your own class: Expand|Select|Wrap|Line Numbers ...              >>> class sm(dict): ...     def __add__(self, other): ...         res = sm() ...         for key, value in other.items(): ...             mine = self.get(key, 0) ...             res[key] = mine + value ...         return res ...      >>> sm_1 = sm({(0,0):5, (0,1):2}) >>> sm_2 = sm({(0,0):7, (0,1):1}) >>> sm_1 + sm_2 {(0, 1): 3, (0, 0): 12} >>>  You'll also need to add some additional logic to account for keys in sm_1 that don't exist in sm_2. Nov 10 '07 #5

 P: 10 hi, before i start asking questions again, i really would like to thank this forum, slowly I was able to form my program, (especially bartonc and bvdet for wasting their time reading my pathetic questions lol), im really glad that someone is helping me... back to my questions... i tried to use the items() but i have error saying: Expand|Select|Wrap|Line Numbers line 17, in __add__     for key, value in self.items(): AttributeError: GeneralSparse instance has no attribute 'items' items() is another function right? but can't i just utilize my __setitem__ and __getitem__, because my __setitem__ already sets the value of my matrix (please correct me if i'm wrong), so because i have set Expand|Select|Wrap|Line Numbers self.matrix[ij] = val on my __setitem__ the value know of my self.matrix is equal to val... i tried to look back on my __str__ method, and tried to pattern some idea then end up with this: Expand|Select|Wrap|Line Numbers     def __add__(self, other):         matrix = m() //i wrote it like this because it will implement my m class         for i in range(self.row):// i like my code to check the row one by one              for j in range(self.col)://before jumping to the next row it has to check first each column that my row has and get the value of it                 self.matrix[i,j] = self[(i,j),0] + other[i,j]   this one didn't give me any error but it also didn't give me anythng, the output is like this: Expand|Select|Wrap|Line Numbers [0  0  0  0  0  0  0    0  0  0  0  0  0  0    0  5  0  0  0  0  0    0  0  4  0  0  0  0    0  0  0  0  0  0  0    0  0  0  0  0  0  0    0  0  0  0  0  0  0  ]   [0  0  0  0  0  0  0    0  0  0  0  0  0  0    0  8  0  0  0  0  0    0  0  1  0  0  0  0    0  0  0  0  0  0  0    0  0  0  0  0  0  0    0  0  0  0  0  0  0  ]   None i don't understand why it is giving me "NONE" then i tried this one also: Expand|Select|Wrap|Line Numbers self.matrix[i,j] = self[.get(i,j),0] + other[i,j] python gave me this error: Expand|Select|Wrap|Line Numbers line 19, in __add__     self.matrix[i,j] = self.get[(i,j),0] + other[i,j] AttributeError: GeneralSparse instance has no attribute 'get' i don't know how to interpret the errors python's throwing me..hope you can help me how to figure it out Nov 10 '07 #6

 Expert 5K+ P: 6,596 hi, i would like to add my two matrices, using __add__ Expand|Select|Wrap|Line Numbers class m:       def __init__(self, mtx={}, m=0, n=0):         self.matrix = {}         self.matrix.update(mtx)         self.row = m         self.col = n       def __getitem__(self, ij):         return self.matrix.get(ij,0)       def __setitem__(self, ij, val):         self.matrix[i,j] = val       def __add__(self, other):         result = m()         for i in other:             self.result[i] = self.matrix.get(i, 0) + other[i]         return result            but i always get an error. Hope you can help me Expand|Select|Wrap|Line Numbers # don't forget that you may want to use print statements with your object     def __repr__(self):         return str(self.matrix)       def __getitem__(self, ij): # this is the syntax for calling with a tuple         return self.matrix.get(ij, 0)       def __setitem__(self, ij, val):         self.matrix[ij] = val  # your version lacked consistance   sm_1 = sm({(0,0):5, (0,1):2}) sm_1[(0,2)] = 8 print sm_1 print sm_1[(0,2)] Nov 10 '07 #7

 P: 10 Expand|Select|Wrap|Line Numbers # don't forget that you may want to use print statements with your object     def __repr__(self):         return str(self.matrix)       def __getitem__(self, ij): # this is the syntax for calling with a tuple         return self.matrix.get(ij, 0)       def __setitem__(self, ij, val):         self.matrix[ij] = val  # your version lacked consistance   sm_1 = sm({(0,0):5, (0,1):2}) sm_1[(0,2)] = 8 print sm_1 print sm_1[(0,2)] Expand|Select|Wrap|Line Numbers     def __getitem__(self, ij): # this is the syntax for calling with a tuple         return self.matrix.get(ij, 0)       def __setitem__(self, ij, val):         self.matrix[ij] = val  # your version lacked consistance what do you mean my version lacked consistence? do i need to add something? because what i understand about getitem and setitem is: 1. __getitem__ will get the index, if the dictionary that have been passed has no tuple it will assign 0 value but if it has then it will get the index or call the tuple 2. __setitem__ will take the index that __getitem__ got and assigned the value that the tuples has. **please correct me if I am wrong** Expand|Select|Wrap|Line Numbers # don't forget that you may want to use print statements with your object this is my __str__() Expand|Select|Wrap|Line Numbers     def __str__(self):         s = "["         if self.row > 0:             for i in range(self.row):                 for j in range(self.col):                     s += str(self[i,j])                     s += "  "                 if i < self.row-1:                     s += "\n "             s += "]\n"             return s isn't it that __str__() does the job in printing my code? because, for this program all we have to do is to complete the methods (__init__, __getitem__, __setitem__, __add__, __mul__, __str__) thanks Nov 11 '07 #8

 Expert 5K+ P: 6,596 isn't it that __str__() does the job in printing my code? Yes. That's correct. If there is not __str__(), then __repr__() gets called, though. It means "representation". Nov 11 '07 #9

 Expert 5K+ P: 6,596 what do you mean my version lacked consistence? Yours had a comma between i & j. There is no comma in mine (which I tested). Nov 11 '07 #10

 Expert 5K+ P: 6,596 this is my __str__() Very nice . Nov 11 '07 #11

 P: 10 this is my whole program Expand|Select|Wrap|Line Numbers class GeneralSparse:       def __init__(self, mtx={}, m=0, n=0):         self.matrix = {}         self.matrix.update(mtx)         self.row = m         self.col = n       def __getitem__(self, ij):         return self.matrix.get(ij,0)       def __setitem__(self, ij, val):         self.matrix[ij] = val       def __add__(self, other):         matrix = GeneralSparse()         for i in range(self.row):             for j in range(self.col):                 self.matrix[i,j] = self[(i,j),0] + other[i,j]            def __str__(self):         s = "["         if self.row > 0:             for i in range(self.row):                 for j in range(self.col):                     s += str(self[i,j])                     s += "  "                 if i < self.row-1:                     s += "\n "             s += "]\n"             return s     if __name__=="__main__":     x = GeneralSparse({(3,2):4, (2,1):5}, 7, 7)     y = GeneralSparse({(3,2):1, (2,1):8}, 7, 7)     print x     print y     a = x + y     print a so far everything works pretty fine. it displays my two matrices but doesn't add them up, and gives me "NONE" i can't still seem to figure out what's wrong or missing in my __add__(). and why it doesn't work [ Nov 11 '07 #12

 Expert 5K+ P: 6,596 this is my whole program Expand|Select|Wrap|Line Numbers class GeneralSparse:       def __init__(self, mtx={}, m=0, n=0):         self.matrix = {}         self.matrix.update(mtx)         self.row = m         self.col = n       def __getitem__(self, ij):         return self.matrix.get(ij,0)       def __setitem__(self, ij, val):         self.matrix[ij] = val       def __add__(self, other):         matrix = GeneralSparse()         for i in range(self.row):             for j in range(self.col):                 self.matrix[i,j] = self[(i,j),0] + other[i,j]            def __str__(self):         s = "["         if self.row > 0:             for i in range(self.row):                 for j in range(self.col):                     s += str(self[i,j])                     s += "  "                 if i < self.row-1:                     s += "\n "             s += "]\n"             return s     if __name__=="__main__":     x = GeneralSparse({(3,2):4, (2,1):5}, 7, 7)     y = GeneralSparse({(3,2):1, (2,1):8}, 7, 7)     print x     print y     a = x + y     print a so far everything works pretty fine. it displays my two matrices but doesn't add them up, and gives me "NONE" i can't still seem to figure out what's wrong or missing in my __add__(). and why it doesn't work [ You get None because you don't return a result. I've crafted an __add__() that may do more than you need, but you may learn a lot from these techniques: Expand|Select|Wrap|Line Numbers #.....     def __add__(self, other):         res = sm({}, self.row, self.col)         for i in range(self.row):             for j in range(self.col):                 try: # does the left hand matrix have this element?                     mine = self.matrix[(i, j)]                     # Yes. try to get() from other or use zero                     res.matrix[(i, j)] = mine + other.matrix.get((i, j), 0)                 except KeyError: # No, does the right hand one?                     try:                         # yes. add it to the resulting matrix                         res.matrix[(i, j)] = other.matrix[(i, j)]                     except KeyError: # No                         pass # do nothing         return res   sm_1 = sm({(3,2):4, (2,1):5}, 7, 7) sm_2 = sm({(3,2):1, (2,1):8}, 7, 7) smSum = sm_1 + sm_2 print smSum # this is from my repr() method {(3, 2): 5, (2, 1): 13} Not that =python only go in the opening CODE tag. Thanks for paying attention to the post that you have seen in this regard. Nov 11 '07 #13

 Expert 5K+ P: 6,596 You get None because you don't return a result. I've crafted an __add__() that may do more than you need, but you may learn a lot from these techniques: Expand|Select|Wrap|Line Numbers #.....     def __add__(self, other):         res = sm({}, self.row, self.col)         for i in range(self.row):             for j in range(self.col):                 try: # does the left hand matrix have this element?                     mine = self.matrix[(i, j)]                     # Yes. try to get() from other or use zero                     res.matrix[(i, j)] = mine + other.matrix.get((i, j), 0)                 except KeyError: # No, does the right hand one?                     try:                         # yes. add it to the resulting matrix                         res.matrix[(i, j)] = other.matrix[(i, j)]                     except KeyError: # No                         pass # do nothing         return res   sm_1 = sm({(3,2):4, (2,1):5}, 7, 7) sm_2 = sm({(3,2):1, (2,1):8}, 7, 7) smSum = sm_1 + sm_2 print smSum # this is from my repr() method {(3, 2): 5, (2, 1): 13} Not that =python only go in the opening CODE tag. Thanks for paying attention to the post that you have seen in this regard. Here are some mods: Expand|Select|Wrap|Line Numbers #     def __getitem__(self, ij):         # Use self.matrix.get() if you really want zero for non-existent elements         return self.matrix[ij]         # If you don't use self.matrix.get() then you can eliminate matrix below (mostly)         # as shown here:       def __add__(self, other):         res = sm({}, self.row, self.col)         for i in range(self.row):             for j in range(self.col):                 try: # does the left hand matrix have this element?                     mine = self[(i, j)]                     # Yes. try to get() from other or use zero                     res[(i, j)] = mine + other.matrix.get((i, j), 0) # using a subclass avoids the .matrix                 except KeyError: # No, does the right hand one?                     try:                         # yes. add it to the resulting matrix                         res[(i, j)] = other[(i, j)]                     except KeyError: # No                         pass # do nothing         return res Nov 11 '07 #14

 Expert 5K+ P: 6,596 Here are some mods: Expand|Select|Wrap|Line Numbers #     def __getitem__(self, ij):         # Use self.matrix.get() if you really want zero for non-existent elements         return self.matrix[ij]         # If you don't use self.matrix.get() then you can eliminate matrix below (mostly)         # as shown here:       def __add__(self, other):         res = sm({}, self.row, self.col)         for i in range(self.row):             for j in range(self.col):                 try: # does the left hand matrix have this element?                     mine = self[(i, j)]                     # Yes. try to get() from other or use zero                     res[(i, j)] = mine + other.matrix.get((i, j), 0) # using a subclass avoids the .matrix                 except KeyError: # No, does the right hand one?                     try:                         # yes. add it to the resulting matrix                         res[(i, j)] = other[(i, j)]                     except KeyError: # No                         pass # do nothing         return res And here it is as a subclass of built-in.dict using if and elif instead of nested try blocks: Expand|Select|Wrap|Line Numbers class smd(dict): # a dictionary like object     def __init__(self, mtx={}, m=0, n=0):         self.update(mtx)         self.row = m         self.col = n       def __add__(self, other):         res = smd({}, self.row, self.col)         for i in range(self.row):             for j in range(self.col):                 if (i, j) in self: # does the left hand matrix have this element?                     mine = self[(i, j)]                     # Yes. try to get() from other or use zero                     res[(i, j)] = mine + other.get((i, j), 0)                 elif (i, j) in other: # No, does the right hand one?                     # yes. add it to the resulting matrix                     res[(i, j)] = other[(i, j)]         return res     sm_1 = smd({(3,2):4, (2,1):5, (2,2):6}, 7, 7) sm_2 = smd({(3,2):1, (2,1):8, (4,4):6}, 7, 7) smSum = sm_1 + sm_2 print smSum # from dict.__str_() {(3, 2): 5, (4, 4): 6, (2, 1): 13, (2, 2): 6} Nov 11 '07 #15

 P: 10 hi bartonc, i tried to follow the your code. i tried to use get() before but python keeps saying that my class has no attribute get, that's why I lose hope using it. thanks for showing me how... i tried to follow your code and this is what i end up with Expand|Select|Wrap|Line Numbers     def __add__(self, other):         result = GeneralSparse()         for i in range(self.row):             for j in range(self.col):                 if (i,j) in self:                     mtx = self[i,j]                     result[(i,j)] = mtx + other.matrix.get((i,j),0)                 elif (i,j) in other:                     result[(i,j)] = other[(i,j),0]         return result can you please check if what's wrong with what i have done because python still complains it just gives back my two matrices and not even saying any error at all just this: Expand|Select|Wrap|Line Numbers IDLE 1.2.1       >>> ================================ RESTART ================================ >>>  [0  0  0  0  0  0  0     0  0  0  0  0  0  0     0  5  0  0  0  0  0     0  0  4  0  0  0  0     0  0  0  0  0  0  0     0  0  0  0  0  0  0     0  0  0  0  0  0  0  ]   [0  0  0  0  0  0  0     0  0  0  0  0  0  0     0  8  0  0  0  0  0     0  0  1  0  0  0  0     0  0  0  0  0  0  0     0  0  0  0  0  0  0     0  0  0  0  0  0  0  ]   Nov 11 '07 #16

 Expert 5K+ P: 6,596 hi bartonc, i tried to follow the your code. i tried to use get() before but python keeps saying that my class has no attribute get, that's why I lose hope using it. thanks for showing me how... i tried to follow your code and this is what i end up with Expand|Select|Wrap|Line Numbers     def __add__(self, other):         result = GeneralSparse()         for i in range(self.row):             for j in range(self.col):                 if (i,j) in self:                     mtx = self[i,j]                     result[(i,j)] = mtx + other.matrix.get((i,j),0)                 elif (i,j) in other:                     result[(i,j)] = other[(i,j),0]         return result can you please check if what's wrong with what i have done because python still complains it just gives back my two matrices and not even saying any error at all just this: Expand|Select|Wrap|Line Numbers IDLE 1.2.1       >>> ================================ RESTART ================================ >>>  [0  0  0  0  0  0  0     0  0  0  0  0  0  0     0  5  0  0  0  0  0     0  0  4  0  0  0  0     0  0  0  0  0  0  0     0  0  0  0  0  0  0     0  0  0  0  0  0  0  ]   [0  0  0  0  0  0  0     0  0  0  0  0  0  0     0  8  0  0  0  0  0     0  0  1  0  0  0  0     0  0  0  0  0  0  0     0  0  0  0  0  0  0     0  0  0  0  0  0  0  ]   Mine works because it is a subclass of bult-in.dict. To make yours work you can add: Expand|Select|Wrap|Line Numbers # this:       def get(self, key, default=None):         return self.matrix.get(key, default) to your class. Or change references from self to self.matrix: Expand|Select|Wrap|Line Numbers     def __add__(self, other):         result = GeneralSparse()         for i in range(self.row):             for j in range(self.col):                 if (i, j) in self.matrix:                     item = self[i,j]                     result[(i,j)] = item + other.matrix.get((i,j), 0)                 elif (i,j) in other.matrix:                     result[(i,j)] = other[(i,j)] # !No default in the getitem() syntax!         return result Nov 11 '07 #17

 Expert Mod 2.5K+ P: 2,851 Mine works because it is a subclass of bult-in.dict. To make yours work you can add: Expand|Select|Wrap|Line Numbers # this:       def get(self, key, default=None):         return self.matrix.get(key, default) to your class. Or change references from self to self.matrix: Expand|Select|Wrap|Line Numbers     def __add__(self, other):         result = GeneralSparse()         for i in range(self.row):             for j in range(self.col):                 if (i, j) in self.matrix:                     item = self[i,j]                     result[(i,j)] = item + other.matrix.get((i,j), 0)                 elif (i,j) in other.matrix:                     result[(i,j)] = other[(i,j)] # !No default in the getitem() syntax!         return result What if there are more rows and/or columns on 'other'? Will the new instance object have any rows or columns if none are assigned? GeneralSparse() __init__ method defaults to 0 rows and columns. I took a different but less elegant approach: Expand|Select|Wrap|Line Numbers ....def __add__(self, other):         dd = {}         # add all keys found in self and other         keys = self.matrix.keys()         for key in keys:             dd[key] = self.matrix[key] + other.matrix.get(key, 0)         # add all keys found in other but not in self         keysOther = other.matrix.keys()         for key in keysOther:             if key not in keys:                 dd[key] = other.matrix[key]         return GeneralSparse(dd, max(self.row, other.row), max(self.col, other.col)) Interactive: Expand|Select|Wrap|Line Numbers >>> z = GeneralSparse({(3,2):1, (2,1):8, (6,4):12}, 7, 7) >>> w = GeneralSparse({(1,2):1, (3,1):8, (6,4):12, (7,8):225.5}, 8, 9) >>> zw = z+w >>> print zw [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 0 0 0 0 0 0 0 0 0 0 0 0 225.5] >>>  Here is another version that produces a slightly different resulting instance: Expand|Select|Wrap|Line Numbers ....def __add__(self, other):         keys = []         for key in self.matrix.keys()+other.matrix.keys():             if key not in keys:                 keys.append(key)         dd = {}         for key in keys:             dd[key] = self.matrix.get(key,0)+other.matrix.get(key,0)         return GeneralSparse(dd, max([i for i in keys])+1, max([j for j in keys])+1) The OP's __str__ method looked OK and seemed to work properly, but we can eliminate string concatenation by using the list method 'join()'. The following uses a list comprehension to accomplish this: Expand|Select|Wrap|Line Numbers ....def __str__(self):         return '[%s]' % '\n'.join([' '.join([str(self[i,j]) for j in range(self.col)]) for i in range(self.row)]) The following does basically the same thing without a list comprehension: Expand|Select|Wrap|Line Numbers ....def __str__(self):         res = []         for i in range(self.row):             seq = []             for j in range(self.col):                 seq.append(str(self[i,j]))             res.append(' '.join(seq))         return '[%s]' % '\n'.join(res) Nov 12 '07 #18

 Expert 5K+ P: 6,596 Thanks for joining in, here, bvdet. Granted, you are far more experienced with these dictionary extensions that I am; I thought that maybe you were just keeping an eye out to see where I'd end up going with this one. Also, please note that this is a coursework thread and I must encourage experts to keep full solutions to themselves (per site rules). Nov 12 '07 #19 