Filter or subtract counter or similar

I have Counter (from collections ) and you want to filter out a set of unwanted elements. The result should be a new counter (or, if you want, do it in place) containing only elements that do not match the property. I tried using filter in Counter , but the result is no longer Counter , but just list . I also tried to subtract a set unwanted elements from this Counter , but this operation is not implemented. Subtracting Counter works, but I don’t have a second Counter , and creating it is essentially the same task that I am trying to accomplish.

 Counter([ 1,2,3,4,5,6,7,6,5,4,3,2,3,4,5,6,5,4,3,4,5,4 ]) β†’ Counter({4: 6, 5: 5, 3: 4, 6: 3, 2: 2, 1: 1, 7: 1}) 

Now I want to remove all values 2 and 3 from this counter, so the result should be

 Counter({4: 6, 5: 5, 6: 3, 1: 1, 7: 1}) 

Here are my approaches:

 filter(lambda x: x not in (2, 3), c) β†’ [1, 4, 5, 6, 7] 

But I do not need a list.

 c - set([ 2, 3 ]) β†’ TypeError: unsupported operand type(s) for -: 'Counter' and 'set' 

I can use sth, which iterates over the unpacked list of items in Counter as follows:

 Counter(x for x in c.elements() if x not in (2, 3)) β†’ Counter({4: 6, 5: 5, 6: 3, 1: 1, 7: 1}) 

but it is obviously unreasonably expensive for large volumes.

The only (not very pleasant) solution I found is cumbersome:

 Counter({ k: v for k, v in c.iteritems() if k not in (2, 3) }) 

Is there anything better, lighter, more readable that I miss?

Why is there no simple subtraction operator for Counter that can be used with set ?

+4
source share
3 answers

Just use del :

 >>> c = Counter([ 1,2,3,4,5,6,7,6,5,4,3,2,3,4,5,6,5,4,3,4,5,4 ]) >>> c Counter({4: 6, 5: 5, 3: 4, 6: 3, 2: 2, 1: 1, 7: 1}) >>> del c[2] >>> del c[3] >>> c Counter({4: 6, 5: 5, 6: 3, 1: 1, 7: 1}) >>> 

Just for fun, you can subtract another Counter with large values ​​for deleting keys, but it's better to stick with del :

 >>> c = Counter([ 1,2,3,4,5,6,7,6,5,4,3,2,3,4,5,6,5,4,3,4,5,4 ]) >>> c Counter({4: 6, 5: 5, 3: 4, 6: 3, 2: 2, 1: 1, 7: 1}) >>> c - Counter({2:sys.maxint, 3:sys.maxint}) Counter({4: 6, 5: 5, 6: 3, 1: 1, 7: 1}) 
+3
source

Try the following:

 from collections import Counter c=Counter([ 1,2,3,4,5,6,7,6,5,4,3,2,3,4,5,6,5,4,3,4,5,4 ]) c2=Counter() for x in c.most_common(): if x[1]<2 or x[1]>3: c2[x[0]]+=x[1] print(c2) 
+1
source

You can use pop - it's faster than using del or understanding a dictionary.

 def alt(): C = Counter([ 1,2,3,4,5,6,7,6,5,4,3,2,3,4,5,6,5,4,3,4,5,4]) for k in C.keys(): if k in (2, 3): del C[k] def alt2(): C = Counter([ 1,2,3,4,5,6,7,6,5,4,3,2,3,4,5,6,5,4,3,4,5,4]) for k in C.keys(): if k in (2, 3): C.pop(k) def alt3(): C = Counter([ 1,2,3,4,5,6,7,6,5,4,3,2,3,4,5,6,5,4,3,4,5,4]) Counter({ k: v for k, v in c.iteritems() if k not in (2, 3) }) 

IPython:

 >>> %timeit alt() 100000 loops, best of 3: 9.66 Β΅s per loop >>> %timeit alt2() 100000 loops, best of 3: 8.64 Β΅s per loop >>> %timeit alt3() 100000 loops, best of 3: 11.3 Β΅s per loop 
0
source

Source: https://habr.com/ru/post/1500523/


All Articles