c# – 让Levenstein的距离算法符合我的需求

前端之家收集整理的这篇文章主要介绍了c# – 让Levenstein的距离算法符合我的需求前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我在使用Levenstein距离算法时遇到了一些麻烦.

我使用Levensteins距离算法来比较产品名称和产品名称列表,以找到最接近的匹配.但是,我需要稍微调整一下.我正在使用dotnetperls.com的例子.

假设我有一个来自我自己的数据库的2000个产品名称的列表A.我自己卖掉所有这些产品.

然后我突然从我的一个供应商处获得了一个清单B,其中包含产品名称和每种产品的新价格.这可能每年发生一次以上,所以我想开发软件来手动完成工作.

问题是这个供应商不是很擅长一致性.所以他时不时地对名字做些小改动,这意味着我不能做一个简单的字符串比较.

我已经实现了距离算法,但它并不能满足我的需求. – 还是!

在浏览我的供应商列表时,我遇到了一个名为的产品

American Crew Anti Dandruff Shampoo 250 ml

该产品与我自己的产品成功匹配

American Crew Anti-Dandruff 250 ml.

距离为10.

问题

我还遇到了一个名为的产品

American Crew 3-In-1 Shampoo 450 ml.

这是错误的匹配

American Crew Daily Shampoo 450 ml.

而不是我的

American Crew 3 in 1 450 ml.

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

有任何想法吗?

顺便说一句,我对算法并不是很好,但我相信某种称量可以帮助我在这里.

编辑:

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

解决方法

一种方法是使用多种方法搜索并对每个方法应用权重.我假设你有一些类Item至少有一个字符串Name属性
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)
    };

当您对数据语料库运行时,我收到以下输出

>美国船员Anti Dandruff洗发水250毫升

>美国船员抗头皮屑250毫升
>美国船员每日洗发水450毫升
>美国船员3合1 450毫升

>美国船员3合1洗发水450毫升

>美国船员3合1 450毫升
>美国船员每日洗发水450毫升
>美国船员抗头皮屑250毫升

如果您有更多条件,则只需将它们添加查询中(与其他let子句一起内联)并对其结果应用一些权重.

其他可能的应用程序是“相同顺序的名称组件”:

let or = xp.Zip(yp,(a,b) => String.Compare(a,b,true))
           .TakeWhile(c => c == 0)
           .Count()

猜你在找的C#相关文章