Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 让Levenstein';s距离算法适合我的需要_C#_Algorithm_Levenshtein Distance - Fatal编程技术网

C# 让Levenstein';s距离算法适合我的需要

C# 让Levenstein';s距离算法适合我的需要,c#,algorithm,levenshtein-distance,C#,Algorithm,Levenshtein Distance,我在Levenstein距离算法方面遇到了一些问题 我使用Levensteins距离算法将产品名称与产品名称列表进行比较,以找到最接近的匹配项。但是,我需要稍微调整一下。我使用的例子来自 假设我从自己的数据库中有一个2000个产品名称的列表。这些产品都是我自己卖的 然后突然间,我从我的一个供应商那里得到了一份清单B,上面有产品名称和每种产品的新价格。这种情况可能一年发生不止一次,所以我想开发一个软件来手动完成这项工作 问题是这个供应商不太擅长一致性。因此,他不时地对名称进行一些小的更改,这意味着

我在Levenstein距离算法方面遇到了一些问题

我使用Levensteins距离算法将产品名称与产品名称列表进行比较,以找到最接近的匹配项。但是,我需要稍微调整一下。我使用的例子来自

假设我从自己的数据库中有一个2000个产品名称的列表。这些产品都是我自己卖的

然后突然间,我从我的一个供应商那里得到了一份清单B,上面有产品名称和每种产品的新价格。这种情况可能一年发生不止一次,所以我想开发一个软件来手动完成这项工作

问题是这个供应商不太擅长一致性。因此,他不时地对名称进行一些小的更改,这意味着我无法进行简单的字符串比较

我已经实现了距离算法,但它并不真正适合我的需要然而

在浏览我的供应商名单时,我发现了一种叫做

美国Crew去屑香波250毫升

该产品与我自己的名为

美国船员去屑250毫升

距离为10

问题

我还发现了一种叫做

美国船员三合一洗发水450毫升

这是错配的

美国船员每日洗发水450毫升

而不是我的

美国船员3人,1450毫升

我明白为什么了!但是我不确定我应该如何从这里改变算法

有什么想法吗

顺便说一句,我对算法不是很在行,但我相信某种程度的权衡会对我有所帮助

编辑:


计算时间并不是一个真正的问题。即使它需要十个小时才能完成,但仍然比手动完成要好得多:P

您可以将Levenstein与第二遍合并,不使用-,空格、点,第三遍计算相似的单词,第四遍基于产品名称中的第一个不同单词


也许你可以看看神经网络?创建训练数据库需要很长时间,但也可能是一个答案(或答案的一部分)。

该算法不会为您提供匹配,而是提供距离。因此,在你的问题场景中,你应该比较两个不同句子的距离,最低距离更好,但仍然没有确定的匹配。我想最好的解决方案是根据算法为用户提供不同的产品名称。然后,用户可以做出最终选择。但如果你不介意偶尔出现不匹配的情况,你就会走上正确的道路。只需选择一个数字来表示你仍然认为匹配的距离,但这会给你带来很多错误的答案。

< P>一种方法是使用多种方法来搜索并应用权重。我假设您有一些类
,其中至少有一个字符串
名称
属性:

double levWeight = 1.0;   // adjust these weights as you see fit
double matchWeight = 1.0;

// add whatever to here you'd like
var splitOn = new[] { ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '-' };
Func<string, string[]> split = 
    s => s.Split(splitOn, StringSplitOptions.RemoveEmptyEntries);

var matches =
    from xx in mine
    let xp = split(xx.Name)
    select new {
        Item = xx,
        Matches =
           (from yy in theirs
            let yp = split(yy.Name)

            /* found how many name components match */
            let mm = xp.Intersect(yp, StringComparer.OrdinalIgnoreCase).Count()

            /* find the Levenshtein distance of the two names */
            let ld = LevDist(xx, yy)

            /* weight our two criteria */
            let ww = (matchWeight * mm) + (levWeight / ld)

            /* should match on at least ONE name component */
            where mm > 0
            orderby ww descending
            select yy)
    };

您需要插入一些关于数据的外部知识。例如,在您展示的案例中,“洗发水”一词并不是关于产品的信息(即,它并没有添加关于两种产品是否相似的有用信息)。如果你已经从数据中删除了“洗发水”这个词,那么这个方法就会奏效

所以,您可以做的一件事是通过计算搜索非常频繁的单词(出现在许多单词中),然后从数据中删除,因为它们可能对您的问题没有任何信息。然后运行算法

第二个小调整是使用您关于字符“-”的知识。可以认为此字符类似于空格字符“”。因此,在运行算法之前,将任何“-”替换为“”

这样,您不必更改算法,但仍然可以使用您对问题的知识(我知道您希望避免更改算法)


最后,您可能想考虑更剧烈的变化,例如不使用Levenstein距离或比较整个单词。您不显示数据集,但如果差异出现在少量字符(例如拼写错误)中,则当前使用的形式中的Levenstein距离最好。

我喜欢添加更多过程的想法。非常感谢。不过,神经元网络在这项任务中似乎有点过火了。也许可以修改算法,为那些没有几乎完全匹配的产品提供最接近的4或5个产品的列表。然后你可以很快地手动查看它们并选择正确的一个。是的,我也想到了。这实际上可能是最好的方法。你甚至可以玩转算法,选择一个距离,在这个距离上你知道不可能有一个正确的匹配(比如我头顶上30个左右),并通过这种方式减少一些列表。我想对于大多数产品,如果你这样做的话,你只能得到1到2个选项。另一种选择是:如果你能获得EAN(条形码),你可以尝试匹配它。。。您的问题在于这些项目的标识。您如何订购商品?有没有像#12345?@mortb这样的“项目编号”,这是不可能的,因为我没有选择EAN编号。不错的想法虽然我知道它给了我一个距离,但我只是选择了距离最小的一个。:-)我相信你的想法是保存最好的匹配以供审查,这是更好的选择。哇!谢谢!看起来棒极了。我来试一试;-)我非常感谢你。你救了我整整一周!
let or = xp.Zip(yp, (a,b) => String.Compare(a, b, true))
           .TakeWhile(c => c == 0)
           .Count()