Skip to content
Browse files

`filter_len()` recipe

The `filter_len()` recipe provides the easy ability to find the number
of elements in an iterable that match a certain criteria.

Also ignoring .pyc files in .gitignore.
1 parent 8618ad7 commit 5122dc5e8451fcb741a4b9ff2854e102a811ac06 @mattbasta mattbasta committed
Showing with 44 additions and 4 deletions.
  1. +1 −0 .gitignore
  2. +14 −4 more_itertools/recipes.py
  3. +29 −0 more_itertools/tests/test_recipes.py
View
1 .gitignore
@@ -1 +1,2 @@
.tox
+*.pyc
View
18 more_itertools/recipes.py
@@ -8,14 +8,14 @@
"""
from collections import deque
-from itertools import chain, count, combinations, cycle, groupby, imap, ifilterfalse, islice, izip, izip_longest, repeat, starmap, tee # Wrapping breaks 2to3.
+from itertools import chain, combinations, count, cycle, groupby, ifilter, ifilterfalse, imap, islice, izip, izip_longest, repeat, starmap, tee # Wrapping breaks 2to3.
import operator
from random import randrange, sample, choice
-__all__ = ['take', 'tabulate', 'consume', 'nth', 'quantify', 'padnone',
- 'ncycles', 'dotproduct', 'flatten', 'repeatfunc', 'pairwise',
- 'grouper', 'roundrobin', 'powerset', 'unique_everseen',
+__all__ = ['take', 'tabulate', 'consume', 'nth', 'quantify', 'filter_len',
+ 'padnone', 'ncycles', 'dotproduct', 'flatten', 'repeatfunc',
+ 'pairwise', 'grouper', 'roundrobin', 'powerset', 'unique_everseen',
'unique_justseen', 'iter_except', 'random_product',
'random_permutation', 'random_combination',
'random_combination_with_replacement']
@@ -112,6 +112,16 @@ def quantify(iterable, pred=bool):
return sum(imap(pred, iterable))
+def filter_len(func, iterable):
+ """Returns the number of items in `iterable` where `func(item)` is truthy
+
+ >>> filter_len(lambda x: x % 3 == 0, xrange(1000000))
+ 333334
+
+ """
+ return sum(1 for _ in ifilter(func, iterable))
+
+
def padnone(iterable):
"""Returns the sequence of elements and then returns None indefinitely.
View
29 more_itertools/tests/test_recipes.py
@@ -1,3 +1,4 @@
+from itertools import islice
from unittest import TestCase
from nose.tools import eq_, assert_raises, ok_
@@ -113,6 +114,34 @@ def test_custom_predicate(self):
eq_(quantify(q, lambda x: x % 2 == 0), 5)
+class FilterLenTests(TestCase):
+ """Tests for ``filter_len()``"""
+
+ def test_generators(self):
+ """Test that generators work properly."""
+ def fib():
+ """The Fibonacci Sequence is within."""
+ a, b = 0, 1
+ yield a
+ yield b
+ while 1:
+ a, b = b, a + b
+ yield b
+
+ long_fib = islice(fib(), 100)
+ eq_(filter_len(lambda x: x % 10 == 5, long_fib), 13)
+
+ def test_sequences(self):
+ """Test that sequences work properly."""
+ eq_(filter_len(lambda x: x % 10 == 0, range(101)), 11)
+
+ def test_no_truthiness(self):
+ """Test that truthy values don't muck with the output."""
+ vals = [1, True, "yes", [1, 2, 3]]
+ eq_(filter_len(lambda x: x, vals), len(vals))
+ eq_(filter_len(lambda x: False, vals), 0)
+
+
class PadnoneTests(TestCase):
"""Tests for ``padnone()``"""

0 comments on commit 5122dc5

Please sign in to comment.
Something went wrong with that request. Please try again.