435,358 Members | 2,957 Online + Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,358 IT Pros & Developers. It's quick & easy.

Searching and manipulating lists of tuples

 P: n/a Hello, I'm wondering if there's a quick way of resolving this problem. In a program, I have a list of tuples of form (str,int), where int is a count of how often str occurs e.g. L = [ ("X",1),("Y",2)] would mean "X" occurs once and "Y" occurs twice If I am given a string, I want to search L to see if it occurs already. If it does, I find the corresponding tuple and increment the integer part. If not, I append the new element with int = 1. e.g. algorithm(L, "X") would produce output L = [("X",2),("Y",2)] algorithm(L,"Z") would produce L = [("X",1),("Y",2),("Z",1)] I tried to create an algorithm of the following form: def algorith(list,str): .... flag = True .... for l in list: .... if l == str: .... l += 1 .... flag = False .... if flag: .... list.append((str,1)) .... But: algorith(L,"X") gives: Traceback (most recent call last): File "", line 1, in ? File "", line 5, in algorith TypeError: object does not support item assignment So clearly that doesn't work... any ideas? Jun 12 '06 #1
7 Replies

 P: n/a MTD wrote: Hello, I'm wondering if there's a quick way of resolving this problem. In a program, I have a list of tuples of form (str,int), where int is a count of how often str occurs .... So clearly that doesn't work... any ideas? Yes, use the proper tool for the job. Tuples are immutable (they are read-only once created). Instead use a dictionary. They key would be your string, the value would be the count. Also, don't use 'str' as the name for a string, as it shadows the built-in 'str' function. Jun 12 '06 #2

 P: n/a MTD wrote: Hello, I'm wondering if there's a quick way of resolving this problem. In a program, I have a list of tuples of form (str,int), where int is a count of how often str occurs e.g. L = [ ("X",1),("Y",2)] would mean "X" occurs once and "Y" occurs twice If I am given a string, I want to search L to see if it occurs already. If it does, I find the corresponding tuple and increment the integer part. If not, I append the new element with int = 1. e.g. algorithm(L, "X") would produce output L = [("X",2),("Y",2)] algorithm(L,"Z") would produce L = [("X",1),("Y",2),("Z",1)] I tried to create an algorithm of the following form: def algorith(list,str): ... flag = True ... for l in list: ... if l == str: ... l += 1 ... flag = False ... if flag: ... list.append((str,1)) ... But: algorith(L,"X") gives: Traceback (most recent call last): File "", line 1, in ? File "", line 5, in algorith TypeError: object does not support item assignment Your approach does not work because the tuples in the list a imutable. The problem occurs in the line l += 1. You could solve the problem by using lists of lists, rather than lists of tuples. However, if you only want to know the frequency of items in the list (i.e. want to build a histogram) and you are not interested in the original order of items in the list, a dictionary is suited better for this task, because you avoid the linear time behavior of: def histogram(liste) : result = {} for item in liste : result[item] = result.get(item,0) + 1 return result.items() Jun 12 '06 #3

 P: n/a > Yes, use the proper tool for the job. Tuples are immutable (they are read-only once created). Instead use a dictionary. They key would be your string, the value would be the count. Wow, I really should have thought of that! Thanks. Jun 12 '06 #4

 P: n/a MTD wrote: Hello, I'm wondering if there's a quick way of resolving this problem. In a program, I have a list of tuples of form (str,int), where int is a count of how often str occurs e.g. L = [ ("X",1),("Y",2)] would mean "X" occurs once and "Y" occurs twice If I am given a string, I want to search L to see if it occurs already. If it does, I find the corresponding tuple and increment the integer part. If not, I append the new element with int = 1. e.g. algorithm(L, "X") would produce output L = [("X",2),("Y",2)] algorithm(L,"Z") would produce L = [("X",1),("Y",2),("Z",1)] I tried to create an algorithm of the following form:def algorith(list,str): ... flag = True ... for l in list: ... if l == str: ... l += 1 ... flag = False ... if flag: ... list.append((str,1)) ... But:algorith(L,"X") gives: Traceback (most recent call last): File "", line 1, in ? File "", line 5, in algorith TypeError: object does not support item assignment So clearly that doesn't work... any ideas? [Nit: try not to use built-in names like "list" and "str" for your own purposes, as it stops you from using the bult-ins]. There are many ways you could do this more efficiently. The most efficient solution doesn't use a list at all, but a dictionary (the following code is untested): def algorith(d, s): if s in d: d[s] += 1 else: d[s] = 1 regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC/Ltd http://www.holdenweb.com Love me, love my blog http://holdenweb.blogspot.com Recent Ramblings http://del.icio.us/steve.holden Jun 12 '06 #5

 P: n/a MTD wrote: Hello, I'm wondering if there's a quick way of resolving this problem. In a program, I have a list of tuples of form (str,int), where int is a count of how often str occurs e.g. L = [ ("X",1),("Y",2)] would mean "X" occurs once and "Y" occurs twice If I am given a string, I want to search L to see if it occurs already. If it does, I find the corresponding tuple and increment the integer part. If not, I append the new element with int = 1. e.g. algorithm(L, "X") would produce output L = [("X",2),("Y",2)] algorithm(L,"Z") would produce L = [("X",1),("Y",2),("Z",1)] just a thought: class MyList(object): def __init__(self): self._items = [] self._counts = [] def append(self, value): try: i = self._items.index(value) self._counts[i] += 1 except ValueError: self._items.append(value) self._counts.append(1) def __getitem__(self, index): return self._items[index], self._counts[index] def __repr__(self): return str(zip(self._items, self._counts)) m = MyList() print m m.append('K') print m m.append('K') print m m.append('Z') print m ----------------------------------- Gerard Jun 12 '06 #6

 P: n/a Steve Holden wrote:def algorith(d, s): if s in d: d[s] += 1 else: d[s] = 1 def algorith(d, s): d[s] = d.get(s, 0) + 1 And the OP should note that converting between dict d and list of pairs L is simply a matter of L = d.items() and d = dict(L) (assuming some other part of the program wants that list representation). -- \S -- si***@chiark.greenend.org.uk -- http://www.chaos.org.uk/~sion/ ___ | "Frankly I have no feelings towards penguins one way or the other" \X/ | -- Arthur C. Clarke her nu becomeþ se bera eadward ofdun hlæddre heafdes bæce bump bump bump Jun 12 '06 #7

 P: n/a MTD wrote: Hello, I'm wondering if there's a quick way of resolving this problem. In a program, I have a list of tuples of form (str,int), where int is a count of how often str occurs e.g. L = [ ("X",1),("Y",2)] would mean "X" occurs once and "Y" occurs twice If I am given a string, I want to search L to see if it occurs already. If it does, I find the corresponding tuple and increment the integer part. If not, I append the new element with int = 1. e.g. algorithm(L, "X") would produce output L = [("X",2),("Y",2)] algorithm(L,"Z") would produce L = [("X",1),("Y",2),("Z",1)] if you don't mind about ordering: def algorithm(items, target): d = dict(items) try: d[target] += 1 except KeyError: d[target] = 1 items[:] = d.items() Now it would probably be better to directly use a dict instead of a list of tuples if possible... I tried to create an algorithm of the following form:def algorith(list,str): Using 'list' and 'str' as identifiers will shadow the eponym builtin types in this function. This may or may not be a problem here, but it's usually better to avoid doing so. ... flag = True ... for l in list: ... if l == str: ... l += 1 tuples are immutable. Hence the exception. ... flag = False 'break'ing here would avoid useless iterations. And also allow the use of the 'else' clause of the for loop, si you don't need a flag. ... if flag: ... list.append((str,1)) ... While there are pretty good reasons to favor the dict-based solution (unless you really insist on having sub-optimal code of course !-), the following is a somewhat more pythonic rewrite of your original code: def algogo(alist, astring): for i, (name, count) in enumerate(alist): if name == astring: alist[i] = (name, count+1) break else: alist.append( (astring, 1) ) (snip) -- bruno desthuilliers python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for p in 'o****@xiludom.gro'.split('@')])" Jun 12 '06 #8

This discussion thread is closed

Replies have been disabled for this discussion. 