I'd write it like this: bin = {} for start, end, AS, full in heard: week = int((start-startDate)/aWeek) counters = bin.setdefault(week, [0, 0]) if full: counters[0] += 1 else: counters[1] += 1
for week, (times_full, times_not_full) in bin.iteritems(): print ... Seriously, use setdefault() as often as you can. It may be a little awkward at first, but after a little bit, you instantly know what it means. It takes out a whole if/else statement which will make your code smaller and more readable at the same time. The list is actually representing a struct. Regardless of how it smells, it's tight, small, and elegant. (This is the sort of problem where Python shines.) I do stuff like this all the time. Lists are so lightweight that there really isn't a better way to solve this problem. Anything else either involves more code or is less readable, in my opinion. Using an idea you used earlier, you could get smaller code by saying: for start, end, AS, full in heard: week = int((start-startDate)/aWeek) counters = bin.setdefault(week, [0, 0]) counters[not full] += 1 Or for start, end, AS, full in heard: week = int((start-startDate)/aWeek) bin.setdefault(week, [0, 0])[not full] += 1 Or even for start, end, AS, full in heard: bin.setdefault(int((start-startDate)/aWeek), [0, 0])[not full] += 1 While smaller, those are all too tricky for my taste. I think they're harder to read. I'd personally use the if/else. YMMV. Using lists to represent structs is perfectly fine if the list doesn't live longer than about one screen of code. If the list-struct gets returned from a top-level function and gets used elsewhere, then you should start to worry. It's too easy to forget what each element is supposed to represent if you have to scroll your editor to see the place where the list was created. That, in my opinion, would smell fishy. In that case, you should probably represent your struct with a class or a dict so that each element has a name. On the flip side, using such a heavy solution for such a simple problem also smells bad. The solution should should be as complicated as the problem -- no more, no less. Adam Randy Bush wrote: >>> bin = {} >>> for whatever: >>> for [a, b] in foo: >>> x = 42 - a >>> if bin.has_key(x): >>> bin[x.b] += 1 >>> else: >>> bin[x.b] = 1 >>> bin[x.not b] = 0 >>> for x, y, z in bin.iteritems(): >>> print x, y, z >>> >>>should the dict value become a two element list, or is there a >>>cleaner way to do this? >> >>It would probably help if you explained what the real problem is >>you're trying to solve. > > > actually, that code fragment was meant to do that. it's pretty much > what i needed to do at that point, just the variable names made > simple. > > >>Using a two element list to store a pair of counts has a bad code >>smell to me. > > > exactly. which is why i was asking. > > >>That said, you could write your code something like: >> bin = {} >> for whatever: >> # NOTE: brackets are unnecessary >> for a, b in foo: >> x = 42 - a >> # NOTE: 'in' is generally faster than has_key() >> if x in bin >> bin[x][0] += 1 >> else: >> bin[x] = [1, 0] >> # NOTE: extra parens necessary to unpack count list >> for x, (y, z) in bin.iteritems(): >> print x, y, z > > > so, to do this using the real names, it looks like > > for [start, end, AS, full] in heard: > week = int((start-startDate)/aWeek) > if week in bin: > if full: > bin[week][0] += 1 > else: > bin[week][1] += 1 > else: > if full: > bin[week] = [1, 0] > else: > bin[week] = [0, 1] > ... > for i, (j, k) in bin.iteritems(): > if j == 0: > print str(i) + ",," + str(k) > elif k == 0: > print str(i) + "," + str(j) > else: > print str(i) + "," + str(j) + "," + str(k) > > which is still pretty darned grotty and unexpressive. of course, > i could be a bit more obscure and do > > if week in bin: > bin[week][not full] += 1 > else: > bin[week] = [ full, not full ] > > except i probably have to coerce the types or something. less > code but less obvious. > > randy > -- http://mail.python.org/mailman/listinfo/python-list