1

I've a nested list in the format:

[[a1, b1, c1, d1], [a2, b2, c2, d2], [a3, b3, c3, d3]]

For each sub-list, I'd like to count the number of times a (a1, a2, a3, ...) appears in any of the sub-lists (since a can potentially appear in multiple sub-lists), and then insert it back into the current sub-list that I'm iterating through.

I've read the threads here and here, and have attempted to do this like so:

for sl in list_in:  # Iterate through each sub-list in the big list
    c_umi = sl[0]  # "c_umi" is "a" in my example above; i.e. extract each "a" value from the big list
    u_count = list_in.count(any(c_umi in s_list for s_list in list_in))  # Count the number of times "c_umi" appears in any of the sub-lists in the entire big list, not just the sub-list I'm iterating over at the moment
    sl.insert(2, u_count)  # Insert the count into index #2 of the current sub-list

I'm not getting any python errors, but the count keeps returning 0. So the value "0" keeps getting inserted into my sub-list, when I can plainly see that there is in fact a that exists at least once in the sub-list!

Here is a screenshot:

"u_count" is 0, but I definitely have at least 1 value in "list_in"

I suspect my list comprehension is incorrect. Does anyone know why this isn't counting correctly?

Alureon
  • 179
  • 1
  • 3
  • 14
  • Is the first value in every sub-list guaranteed to be an `a` value? – Christian Dean Feb 05 '18 at 18:15
  • 1
    modifying lists while iterating over them is dangerous – Patrick Artner Feb 05 '18 at 18:16
  • is your `'a1'`, `'a2'`, `'a3'`, .... strings? and you are trying to check whether `'a'` is present as substring? – Moinuddin Quadri Feb 05 '18 at 18:17
  • 2
    @PatrickArtner Normally I'd agree with you, but he's not modifying the list object he's iterating over. He's modifying a (list) object _in_ the list he is iterating over. That's perfectly fine. – Christian Dean Feb 05 '18 at 18:18
  • @ChristianDean Yes, the first value in every sub-list is always going to be an `a` value (no matter how many sub-lists there are). – Alureon Feb 05 '18 at 18:54
  • @MoinuddinQuadri Yes, the `a` values are always strings, but I don't need to check if they exist in the sub-list; I know they will always be there! I just need to see if they exist in any **other** sub-lists in the entire big list (`list_in` variable). – Alureon Feb 05 '18 at 18:55

1 Answers1

2

Your problem is with this:

list_in.count(any(c_umi in s_list for s_list in list_in))

any always returns a boolean, which is never in list_in, which consists entirely of list objects. A bool will never equal a list, which is why you always get a count of 0.

To make this work, you could have done something like:

u_count = sum(c_umi in s_list for s_list in list_in)

But this would be grossly inefficient.

You can do this much more efficiently. You should do a single pass over your list and get a dictionary of counts, and use that dictionary in second pass to add your values into your sublists (as an aside, you should choose a better container than a list to use as a record, perhaps a namedtuple, also, .insert into a list is inefficient, but since your sublists are small, it probably isn't a big deal...).

from collections import Counter
counts = Counter(sublist[0] for sublist in list_in)
for sublist in list_in:
    sublist.insert(2, counts[sublist[0]])
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
  • Thanks for explaining the boolean logic behind `any()` and `list` objects! But if I'd used a tuple (or `namedtuple`) as you suggested, I wouldn't be able to insert the count into the sublist (or subtuple), since tuples are immutable, right? And I thought about using `set()`, but sets are unordered, and I need the order for each sublist (or subset) to be fixed (i.e. `a` must be in position 1, `b` must be in position 2, etc.). – Alureon Feb 05 '18 at 19:17
  • 1
    @WaterGuy define a `namedtuple` with a field that will contain this count ahead of time. Fill it with `None` until you do. In general,y ou should try to organize your program's data-structures as much as possible ahead of time – juanpa.arrivillaga Feb 05 '18 at 19:25