From 4a9e2ecd87738236f9ac95561f4072e16f5c607a Mon Sep 17 00:00:00 2001 From: Uday Patel Date: Wed, 21 Jan 2026 15:52:55 -0500 Subject: [PATCH] feat: optimize collections.Counter.most_common() when n == 1; add tests for coverage; add NEWS file --- Lib/collections/__init__.py | 7 +++++++ Lib/test/test_collections.py | 18 ++++++++++++++++++ ...6-01-21-15-46-53.gh-issue-144127.aBc123.rst | 3 +++ 3 files changed, 28 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-01-21-15-46-53.gh-issue-144127.aBc123.rst diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 55ffc36ea5b0c7..21459337ca18b3 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -634,6 +634,13 @@ def most_common(self, n=None): if n is None: return sorted(self.items(), key=_itemgetter(1), reverse=True) + if n == 1: + # Optimization: use max() instead of heapq for single element + # max() raises ValueError on empty sequence, so check first + if not self: + return [] + return [max(self.items(), key=_itemgetter(1))] + # Lazy import to speedup Python startup time global heapq if heapq is None: diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index b1b2dd2ca5ca0d..935edf58a29025 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -2279,6 +2279,24 @@ def test_invariant_for_the_in_operator(self): self.assertTrue(elem in c) self.assertIn(elem, c) + def test_most_common(self): + c = Counter(a=5, b=3, c=5, d=2, e=0, f=-1) + + self.assertEqual(c.most_common(), [('a', 5), ('c', 5), ('b', 3), ('d', 2), ('e', 0), ('f', -1)]) + self.assertEqual(c.most_common(3), [('a', 5), ('c', 5), ('b', 3)]) + self.assertEqual(c.most_common(0), []) + self.assertEqual(c.most_common(-2), []) + self.assertEqual(c.most_common(1), [('a', 5)]) + + # Test empty counter + empty_c = Counter() + + self.assertEqual(empty_c.most_common(), []) + self.assertEqual(empty_c.most_common(3), []) + self.assertEqual(empty_c.most_common(0), []) + self.assertEqual(empty_c.most_common(-2), []) + self.assertEqual(empty_c.most_common(1), []) + def test_multiset_operations(self): # Verify that adding a zero counter will strip zeros and negatives c = Counter(a=10, b=-2, c=0) + Counter() diff --git a/Misc/NEWS.d/next/Library/2026-01-21-15-46-53.gh-issue-144127.aBc123.rst b/Misc/NEWS.d/next/Library/2026-01-21-15-46-53.gh-issue-144127.aBc123.rst new file mode 100644 index 00000000000000..def589674c2bdd --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-01-21-15-46-53.gh-issue-144127.aBc123.rst @@ -0,0 +1,3 @@ +Optimize :meth:`collections.Counter.most_common` for ``n=1`` to use +:func:`max` instead of :func:`heapq.nlargest`, improving performance for +the common case of finding the single most common element.