By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,358 Members | 2,957 Online
Bytes IT Community
+ 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
MTD
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[0] == str:
.... l[1] += 1
.... flag = False
.... if flag:
.... list.append((str,1))
....
But:
algorith(L,"X")


gives:

Traceback (most recent call last):
File "<interactive input>", line 1, in ?
File "<interactive input>", line 5, in algorith
TypeError: object does not support item assignment
So clearly that doesn't work... any ideas?

Jun 12 '06 #1
Share this Question
Share on Google+
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[0] == str:
... l[1] += 1
... flag = False
... if flag:
... list.append((str,1))
...
But:
algorith(L,"X")


gives:

Traceback (most recent call last):
File "<interactive input>", line 1, in ?
File "<interactive input>", 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] += 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
MTD
> 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[0] == str:
... l[1] += 1
... flag = False
... if flag:
... list.append((str,1))
...
But:

algorith(L,"X")

gives:

Traceback (most recent call last):
File "<interactive input>", line 1, in ?
File "<interactive input>", 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 <st***@holdenweb.com> 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[0] == str:
... l[1] += 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.