Re: [Tutor] list objects are unhashable
Norman Khine [EMAIL PROTECTED] wrote Here is the 'full' code as such which gets the data from the files. Unfortunately trying to read this is still difficult since we don't know what the structure of x, horizontal_criterias, vertical_criterias, or brains is like. ## Classify the users table = {} table[('', '')] = 0 for x in horizontal_criterias: table[(x['id'], '')] = 0 for y in vertical_criterias: table[('', y['id'])] = 0 for x in horizontal_criterias: x = x['id'] You select a collection of some sort and replace it with a value from the collection. Is that really what you want to do? You don't do it for y... for y in vertical_criterias: table[(x, y['id'])] = 0 It would be just as readable IMHO to just use table[ x['id'],y['id'] ] = 0 for brain in brains: x = getattr(brain, horizontal) if isinstance(x, list): for item in x: x = item And here you replace the list x with it' first item. You could just do x = x[0] else: x And this does nothing useful whatsoever. It just siilently evaluates x. y = getattr(brain, vertical) if isinstance(y, list): for item in y: y = item else: y Same comments apply if x and y and (x, y) in table: table[(x, y)] += 1 table[(x, '')] += 1 table[('', y)] += 1 table[('', '')] += 1 table is a dictionary, which returns, for example: { ('', ''): 1, ('', 'fr'): 0, ('airport-car-parking', ''): 2, ('airport-car-parking', 'fr'): 0, ('air-taxi-operators', ''): 1, ('air-taxi-operators', 'fr'): 0, ... ('worldwide-attractions-and-ticket-agents', ''): 0, ('worldwide-attractions-and-ticket-agents', 'fr'): 0, From this I suggest you rename your variable from x and y to something meaningful like facility and country. That might make your code more meaningful to read. The output is something like: country |airport-car|air-taxi-operators|airlines-schedule| total --- france |0 |0|0 |0 uk |2 |0|0 |2 us |0 |0|0 |0 --- total |2 |0 |0 |2 --- What I can't seem to figure out is how to do a cumulative sum for each record, for example, my files contain: Frankly I'd use a database. Just load the data into it using Python. Then execute SQL querioes to get the counts etc. if isinstance(x, list): for item in x: x = item pp.pprint(x) else: Which is correct, but the table only counts the first item of the tuple. Isn't that because you replace x with the first element of x? Alan G. ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] list objects are unhashable
On Tue, Jul 1, 2008 at 3:09 AM, Norman Khine [EMAIL PROTECTED] wrote: x = getattr(brain, horizontal) if isinstance(x, list): for item in x: x = item This just assigns x to the last element of the list, it doesn't process the whole list. One possibility would be to ensure that x and y are always lists, then use nested loops to iterate over all combinations: x = getattr(brain, horizontal) if not isinstance(x, list): x = [x] y = getattr(brain, vertical) if not isinstance(y, list): y = [y] for first in x: for second in y: if first and second and (first, second) in table: etc. Kent ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] list objects are unhashable
Kent Johnson [EMAIL PROTECTED] wrote if isinstance(x, list): for item in x: x = item This just assigns x to the last element of the list Oops, yes, I said the first but in fact reassigning x does not stop the loop, it seems the loop works on a local copy of the original reference. Alan G ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] list objects are unhashable
Kent Johnson wrote: On Tue, Jul 1, 2008 at 3:09 AM, Norman Khine [EMAIL PROTECTED] wrote: x = getattr(brain, horizontal) if isinstance(x, list): for item in x: x = item This just assigns x to the last element of the list, it doesn't process the whole list. One possibility would be to ensure that x and y are always lists, then use nested loops to iterate over all combinations: x = getattr(brain, horizontal) if not isinstance(x, list): x = [x] y = getattr(brain, vertical) if not isinstance(y, list): y = [y] for first in x: for second in y: if first and second and (first, second) in table: I don't really see this clearly as I may have n'th values for 'x' and n'th values for 'y' so I will need to loop over all these, but without knowing the n'th value where to stop my loop? Or have I missed the point ;) etc. Kent ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] list objects are unhashable
On Tue, Jul 1, 2008 at 6:27 AM, Alan Gauld [EMAIL PROTECTED] wrote: Kent Johnson [EMAIL PROTECTED] wrote if isinstance(x, list): for item in x: x = item This just assigns x to the last element of the list Oops, yes, I said the first but in fact reassigning x does not stop the loop, it seems the loop works on a local copy of the original reference. Under the hood, 'for item in x' creates an iterator which has a reference to the original list. Kent ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] list objects are unhashable
Norman Khine [EMAIL PROTECTED] wrote Frankly I'd use a database. Just load the data into it using Python. Then execute SQL querioes to get the counts etc. Not really an option to use SQL just for this. I'm curious why? It seems to suggest that using SQL is somehow a big deal? But with the SqlLite database access that ships with Python 2.5+ the database is just a normal file and you access it using SQL commands. There is no database server or DBA involvement etc. if that is your concern. SqlLite is specifically designed for these kinds of small scale ad-hoc query of complex data type of scenarios. Or is there something else that rules it out? Alan G. ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] list objects are unhashable
Alan Gauld wrote: Norman Khine [EMAIL PROTECTED] wrote Frankly I'd use a database. Just load the data into it using Python. Then execute SQL querioes to get the counts etc. Not really an option to use SQL just for this. I'm curious why? It seems to suggest that using SQL is somehow a big deal? I am not sure how to implement this for now, as I have not used SqlLite. But with the SqlLite database access that ships with Python 2.5+ the database is just a normal file and you access it using SQL commands. There is no database server or DBA involvement etc. if that is your concern. SqlLite is specifically designed for these kinds of small scale ad-hoc query of complex data type of scenarios. I will look into this, but for now, can you advise on how to loop through the list and add each item found to the counter as this is the logic I don't understand. Or is there something else that rules it out? Alan G. ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
[Tutor] list objects are unhashable
Hello, I would like to count list items but am not 100% sure how to do it. Here is what I have so far: for brain in brains: x = getattr(brain, horizontal) y = getattr(brain, vertical) if x and y and (x, y) in table: table[(x, y)] += 1 table[(x, '')] += 1 table[('', y)] += 1 table[('', '')] += 1 but when I run this, I get the following error on the line: if x and y and (x, y) in table: TypeError: list objects are unhashable where: x = ['airlines-scheduled', 'airport-car-parking'] I am basically looping through files within each file, I have an entity, for example: file1 topicairlines-scheduled airport-car-parking/topic file2 topicairport-car-parking/topic etc... So the above code counts all occurrences of 'airport-car-parking' and sums it up. All works well if, I change the code to: for brain in brains: x = getattr(brain, horizontal) x = string.join(x, '' ) y = getattr(brain, vertical) y = string.join(y, '' ) if x and y and (x, y) in table: table[(x, y)] += 1 table[(x, '')] += 1 table[('', y)] += 1 table[('', '')] += 1 So now my list becomes a string, which is not really good for me, as this fails when there is more then one item. Is there a better way to loop through this and sum up all occurrences of each entry ie 'airport-car-parking' Cheers Norman ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] list objects are unhashable
Le Monday 30 June 2008 20:55:36 Norman Khine, vous avez écrit : Hello, I would like to count list items but am not 100% sure how to do it. Here is what I have so far: for brain in brains: x = getattr(brain, horizontal) y = getattr(brain, vertical) if x and y and (x, y) in table: table[(x, y)] += 1 table[(x, '')] += 1 table[('', y)] += 1 table[('', '')] += 1 but when I run this, I get the following error on the line: if x and y and (x, y) in table: TypeError: list objects are unhashable where: x = ['airlines-scheduled', 'airport-car-parking'] lists are not hashable because hashing a mutable type would be dangerous, but tuples are if all their items are hashable too. Just replace x by tuple(x). -- Cédric Lucantis ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] list objects are unhashable
Thanks, but where do i replace the x with tuple(x) Norman Cédric Lucantis wrote: Le Monday 30 June 2008 20:55:36 Norman Khine, vous avez écrit : Hello, I would like to count list items but am not 100% sure how to do it. Here is what I have so far: for brain in brains: x = getattr(brain, horizontal) y = getattr(brain, vertical) if x and y and (x, y) in table: table[(x, y)] += 1 table[(x, '')] += 1 table[('', y)] += 1 table[('', '')] += 1 but when I run this, I get the following error on the line: if x and y and (x, y) in table: TypeError: list objects are unhashable where: x = ['airlines-scheduled', 'airport-car-parking'] lists are not hashable because hashing a mutable type would be dangerous, but tuples are if all their items are hashable too. Just replace x by tuple(x). ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] list objects are unhashable
Le Monday 30 June 2008 21:31:35, vous avez écrit : Thanks, but where do i replace the x with tuple(x) Whenever x is hashed, ie used as a key in a dictionary. You said you have: table[(x, y)] += 1 where: x = ['airlines-scheduled', 'airport-car-parking'] so you should rather write this (if y is a list too): table[(tuple(x), tuple(y))] += 1 but of course you can also use tuples directly if your lists don't have to be modified: x = ('airlines-scheduled', 'airport-car-parking') y = (...) table[(x, y)] += 1 -- Cédric Lucantis ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] list objects are unhashable
Norman Khine [EMAIL PROTECTED] wrote but when I run this, I get the following error on the line: if x and y and (x, y) in table: TypeError: list objects are unhashable Please post the entire error. The tiny bit you posted was not overly helpful, usually the stacjk trace contains the actual cause of the problem or a strong clue. However, in this case... x = ['airlines-scheduled', 'airport-car-parking'] You cannot use a list to access a dictionary because dictionary keys must be immutable, and lists aren't. When you use the 'in' operation on a dictionary it basically searches the keys. I am basically looping through files within each file, I have an entity, for example: file1 topicairlines-scheduled airport-car-parking/topic file2 topicairport-car-parking/topic etc... So the above code counts all occurrences of 'airport-car-parking' and sums it up. All works well if, I change the code to: for brain in brains: x = getattr(brain, horizontal) x = string.join(x, '' ) y = getattr(brain, vertical) y = string.join(y, '' ) if x and y and (x, y) in table: table[(x, y)] += 1 table[(x, '')] += 1 table[('', y)] += 1 table[('', '')] += 1 So now my list becomes a string, which is not really good for me, as this fails when there is more then one item. Use a tuple instead of a list. t = tuple(L) You can use a tuple as an index to a dictionary. HTH, -- Alan Gauld Author of the Learn to Program web site http://www.freenetpages.co.uk/hp/alan.gauld ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] list objects are unhashable
Hi, Sorry, but this did not work. I have done this, which returns the values I want (sort of) for brain in brains: x = getattr(brain, horizontal) if isinstance(x, list): for item in x: x = item else: x y = getattr(brain, vertical) if isinstance(y, list): for item in y: y = item else: y if x and y and (x, y) in table: table[(x, y)] += 1 table[(x, '')] += 1 table[('', y)] += 1 table[('', '')] += 1 The only think is that, the totals are correct, but when there is an item that is in both, it is counted only once. Cédric Lucantis wrote: Le Monday 30 June 2008 21:31:35, vous avez écrit : Thanks, but where do i replace the x with tuple(x) Whenever x is hashed, ie used as a key in a dictionary. You said you have: table[(x, y)] += 1 where: x = ['airlines-scheduled', 'airport-car-parking'] so you should rather write this (if y is a list too): table[(tuple(x), tuple(y))] += 1 but of course you can also use tuples directly if your lists don't have to be modified: x = ('airlines-scheduled', 'airport-car-parking') y = (...) table[(x, y)] += 1 ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] list objects are unhashable
Hi Norman, Norman Khine wrote: for brain in brains: x = getattr(brain, horizontal) x = string.join(x, '' ) y = getattr(brain, vertical) y = string.join(y, '' ) if x and y and (x, y) in table: table[(x, y)] += 1 table[(x, '')] += 1 table[('', y)] += 1 table[('', '')] += 1 For what it's worth, string.join has been deprecated since the addition of the join method for str and unicode types. Other deprecated string module functions are documented here: http://docs.python.org/lib/node42.html If I'm not mistaken, the conventional form would be: x = ''.join(x) So now my list becomes a string, which is not really good for me, as this fails when there is more then one item. Is there a better way to loop through this and sum up all occurrences of each entry ie 'airport-car-parking' Maybe, can you show us a brief excerpt of what 'table' might look like before the loop, and what you expect it to look like after one iteration, with data samples for both x and y? Most likely it's just me, but I'm having trouble reconciling your code examples with your questions. AFAICT, either you want more than just a simple count of occurrences from your data set, or you have some confusion regarding dictionaries (if 'table' is a dictionary, of course). If you want a count of each unique occurrence in a list -- not sure if it's better, but something like this might get you started (untested): from sets import Set x = ['airlines-scheduled', 'airport-car-parking', 'more-than-100ml', 'do-not-bring-toothpaste', 'airport-car-parking', 'airlines-scheduled'] entity_count = dict((item, x.count(item)) for item in Set(x)) print entity_count['airlines-scheduled'] # 2 HTH, Marty ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor