首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python将用户输入与列表中的元素匹配。

Python将用户输入与列表中的元素匹配。
EN

Stack Overflow用户
提问于 2022-09-03 09:24:16
回答 2查看 108关注 0票数 0

我试图将用户输入与列表中的一个元素相匹配。

目标是允许用户不键入元素的全名,因为有超过30个字符的元素:

  1. 结果必须包含输入中的所有字符

例:用户输入foobar与匹配

代码语言:javascript
复制
- `foobarxx`

但不是

代码语言:javascript
复制
- `fobar`

允许输入关键字之间的

  1. 额外字符

例:用户输入abc与:匹配

代码语言:javascript
复制
- `abc`, `a bc`, `axxbxxxc`

  1. 最相关的结果被选中

例:apple pie匹配:

代码语言:javascript
复制
- `apple tasty pie party`, `app legit piece`, `aXpXpXlXeX XpXiXe`

然而,我只想要最相关的结果,那就是apple tasty pie party

我以某种方式取得了以下成绩(1)和(2):

代码语言:javascript
复制
enter = input("input: ")
all_element = ["orange", "apple pie", "pine apple pie", "ppap", "pen pineapple apple pen"]
pattern = ('(?:.+)?'.join(list(enter))).replace(" ", r"\s")
print(pattern)
results = {}
for full_name in all_element:
    all = re.findall(pattern, full_name)
    if all:
        results[len(max(all))] = full_name
print(results)
print(f"result: {results[max(results)]}\n")

结果:

代码语言:javascript
复制
input: pen apple
p(?:.+)?e(?:.+)?n(?:.+)?\s(?:.+)?a(?:.+)?p(?:.+)?p(?:.+)?l(?:.+)?e
{22: 'pen pineapple apple pen'}
result: pen pineapple apple pen

input: ora
o(?:.+)?r(?:.+)?a
{3: 'orange'}
result: orange

我目前正试图解决(3)

根据(3)中的例子,我的计划是看看有多少次中断,我知道:- "apple pie party“破裂了1次,单词”好吃“- "app legit pieece”破裂了2次,一次间隔,一次"git“--”applegitpieece“破裂次数为n(X)次。

选择故障次数最少的结果,即apple tasty pie party

从上面的代码中,我只是使用匹配元素的长度来选择结果,这是不准确的,因为ppap导致的是pen pineapple apple pen而不是ppap本身:

代码语言:javascript
复制
input: ppap
p(?:.+)?p(?:.+)?a(?:.+)?p
{4: 'ppap', 21: 'pen pineapple apple pen'}
result: pen pineapple apple pen

因此,我想知道如何获得基于(?:.+)?的中断次数,在

result应该是:

代码语言:javascript
复制
{0: 'ppap', 2: 'pen pineapple apple pen'}

键是中断次数,项作为选定的元素

这样,我就可以简单地使用min()获得最相关的结果。

问题是,我需要如何编写自己的函数,还是需要使用regex模式来处理这个问题?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-09-03 10:32:06

您可以使用来自Counter模块的collections类来快速消除与前两个条件不匹配的元素。然后,您可以使用SequenceMatcherdifflib中选择其他元素中最相关的选项。

代码语言:javascript
复制
import difflib
from collections import Counter

enter = input("input: ")
all_elements = ["orange", "apple pie", "pine apple pie", "ppap", "pen pineapple apple pen"]
cnts = Counter(enter)
for k,v in cnts.items():
    start = len(all_elements) - 1
    while start >= 0:
        if k not in all_elements[start] or all_elements[start].count(k) < v:
            del all_elements[start]
        start -= 1

results = {}
for elem in all_elements:
    matcher = difflib.SequenceMatcher(a=enter, b=elem)
    num = matcher.quick_ratio()
    blocks = len(matcher.get_matching_blocks())
    results[elem] = (num, blocks)

min_blocks = min([i[1] for i in results.values()])
min_elems = {k:v[0] for k,v in results.items() if v[1] == min_blocks}
print(max(min_elems, key=lambda x: min_elems[x]))
票数 1
EN

Stack Overflow用户

发布于 2022-09-03 16:25:13

另一种比较类似字符串的方法是使用Levenshtein模块。

代码语言:javascript
复制
from Levenshtein import distance as lev

st = "apple pie"
l = ['apple tasty pie party', 'app legit piece', 'aXpXpXlXeX XpXiXe']


def find_best_match(some_list, st):

    return max((lev(st,s), s) for s in some_list)[1]


find_best_match(l, st)

apple tasty pie party
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73591081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档