C# 让Levenstein';s距离算法适合我的需要
我在Levenstein距离算法方面遇到了一些问题 我使用Levensteins距离算法将产品名称与产品名称列表进行比较,以找到最接近的匹配项。但是,我需要稍微调整一下。我使用的例子来自 假设我从自己的数据库中有一个2000个产品名称的列表。这些产品都是我自己卖的 然后突然间,我从我的一个供应商那里得到了一份清单B,上面有产品名称和每种产品的新价格。这种情况可能一年发生不止一次,所以我想开发一个软件来手动完成这项工作 问题是这个供应商不太擅长一致性。因此,他不时地对名称进行一些小的更改,这意味着我无法进行简单的字符串比较 我已经实现了距离算法,但它并不真正适合我的需要然而 在浏览我的供应商名单时,我发现了一种叫做 美国Crew去屑香波250毫升 该产品与我自己的名为 美国船员去屑250毫升 距离为10 问题 我还发现了一种叫做 美国船员三合一洗发水450毫升 这是错配的 美国船员每日洗发水450毫升 而不是我的 美国船员3人,1450毫升 我明白为什么了!但是我不确定我应该如何从这里改变算法 有什么想法吗 顺便说一句,我对算法不是很在行,但我相信某种程度的权衡会对我有所帮助 编辑:C# 让Levenstein';s距离算法适合我的需要,c#,algorithm,levenshtein-distance,C#,Algorithm,Levenshtein Distance,我在Levenstein距离算法方面遇到了一些问题 我使用Levensteins距离算法将产品名称与产品名称列表进行比较,以找到最接近的匹配项。但是,我需要稍微调整一下。我使用的例子来自 假设我从自己的数据库中有一个2000个产品名称的列表。这些产品都是我自己卖的 然后突然间,我从我的一个供应商那里得到了一份清单B,上面有产品名称和每种产品的新价格。这种情况可能一年发生不止一次,所以我想开发一个软件来手动完成这项工作 问题是这个供应商不太擅长一致性。因此,他不时地对名称进行一些小的更改,这意味着
计算时间并不是一个真正的问题。即使它需要十个小时才能完成,但仍然比手动完成要好得多: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()