From 5d06e0ce211044fe33ac8c1513c096213a2f1141 Mon Sep 17 00:00:00 2001 From: Mustafa Quraish Date: Sun, 16 May 2021 12:16:37 -0400 Subject: [PATCH 1/4] add `key` argument to difflib.get_close_matches --- Lib/difflib.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Lib/difflib.py b/Lib/difflib.py index 0dda80d38757399..12b87002f8430d8 100644 --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -1,7 +1,7 @@ """ Module difflib -- helpers for computing deltas between objects. -Function get_close_matches(word, possibilities, n=3, cutoff=0.6): +Function get_close_matches(word, possibilities, n=3, cutoff=0.6, key=None): Use SequenceMatcher to return list of the best "good enough" matches. Function context_diff(a, b): @@ -695,7 +695,7 @@ def real_quick_ratio(self): __class_getitem__ = classmethod(GenericAlias) -def get_close_matches(word, possibilities, n=3, cutoff=0.6): +def get_close_matches(word, possibilities, n=3, cutoff=0.6, key=None): """Use SequenceMatcher to return list of the best "good enough" matches. word is a sequence for which close matches are desired (typically a @@ -710,11 +710,18 @@ def get_close_matches(word, possibilities, n=3, cutoff=0.6): Optional arg cutoff (default 0.6) is a float in [0, 1]. Possibilities that don't score at least that similar to word are ignored. + Optional arg key specifies a function of one argument that is used to + extract a comparison key from each element in iterable (for example, + key=str.lower). The default value is None (compare the elements directly). + The best (no more than n) matches among the possibilities are returned in a list, sorted by similarity score, most similar first. >>> get_close_matches("appel", ["ape", "apple", "peach", "puppy"]) ['apple', 'ape'] + >>> get_close_matches("appel", [("aple", 9), ("peach", 8), ("puppy", 7)], + ... key=lambda x: x[0]) + [('aple', 9)] >>> import keyword as _keyword >>> get_close_matches("wheel", _keyword.kwlist) ['while'] @@ -732,7 +739,10 @@ def get_close_matches(word, possibilities, n=3, cutoff=0.6): s = SequenceMatcher() s.set_seq2(word) for x in possibilities: - s.set_seq1(x) + if key is None: + s.set_seq1(x) + else: + s.set_seq1(key(x)) if s.real_quick_ratio() >= cutoff and \ s.quick_ratio() >= cutoff and \ s.ratio() >= cutoff: From 107e28ea5762b7ce2badf9943ca9a2615f1458b6 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sun, 16 May 2021 16:46:02 +0000 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-05-16-16-46-01.bpo-44149.2MUHbG.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-05-16-16-46-01.bpo-44149.2MUHbG.rst diff --git a/Misc/NEWS.d/next/Library/2021-05-16-16-46-01.bpo-44149.2MUHbG.rst b/Misc/NEWS.d/next/Library/2021-05-16-16-46-01.bpo-44149.2MUHbG.rst new file mode 100644 index 000000000000000..af7f92f3649a5a2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-05-16-16-46-01.bpo-44149.2MUHbG.rst @@ -0,0 +1 @@ +Add a ``key`` argument to :func:`difflib.get_close_matches`. \ No newline at end of file From acc2c2fcc565a2e390c95258e778516237d47f27 Mon Sep 17 00:00:00 2001 From: Mustafa Quraish Date: Mon, 17 May 2021 09:50:24 -0400 Subject: [PATCH 3/4] Remove trailing whitespace in docs --- Lib/difflib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/difflib.py b/Lib/difflib.py index 12b87002f8430d8..894c40c50d6c701 100644 --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -710,8 +710,8 @@ def get_close_matches(word, possibilities, n=3, cutoff=0.6, key=None): Optional arg cutoff (default 0.6) is a float in [0, 1]. Possibilities that don't score at least that similar to word are ignored. - Optional arg key specifies a function of one argument that is used to - extract a comparison key from each element in iterable (for example, + Optional arg key specifies a function of one argument that is used to + extract a comparison key from each element in iterable (for example, key=str.lower). The default value is None (compare the elements directly). The best (no more than n) matches among the possibilities are returned From 04bdeeb40ebaecb0648e38629617f57907192d60 Mon Sep 17 00:00:00 2001 From: Mustafa Quraish Date: Tue, 18 May 2021 18:51:01 -0400 Subject: [PATCH 4/4] Update the documentation --- Doc/library/difflib.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Doc/library/difflib.rst b/Doc/library/difflib.rst index aa08988c8b36f71..45b26270205e370 100644 --- a/Doc/library/difflib.rst +++ b/Doc/library/difflib.rst @@ -205,11 +205,19 @@ diffs. For comparing directories and files, see also, the :mod:`filecmp` module. Optional argument *cutoff* (default ``0.6``) is a float in the range [0, 1]. Possibilities that don't score at least that similar to *word* are ignored. + Optional arg *key* (default ``None``) specifies a function of one argument that + is used to extract a comparison key from each element in *possibilities* + (for example, ``key=str.lower``). If the value is ``None``, the elements are + compared with *word* directly. + The best (no more than *n*) matches among the possibilities are returned in a list, sorted by similarity score, most similar first. >>> get_close_matches('appel', ['ape', 'apple', 'peach', 'puppy']) ['apple', 'ape'] + >>> get_close_matches("appel", [("aple", 9), ("peach", 8), ("puppy", 7)], + ... key=lambda x: x[0]) + [('aple', 9)] >>> import keyword >>> get_close_matches('wheel', keyword.kwlist) ['while']