根据相似性比较字符串

时间:2012-06-21 09:00:49

标签: c# .net regex

我有两个列表,它们看起来像这样

<List> ads
[0]
Headline = "Sony Ericsson Arc silver"
[1]
Headline = "Sony Ericsson Play R800I"


<List> feedItems
[0]
Headline = "Sony Ericsson Xperia Arc Silver"
[1]
Headline = "Sony Ericsson Xperia Play R800i Black"

创建新的第三个列表的最简单方法是什么,其中的元素彼此匹配至少两个字?你能用LINQ方式完成这个吗?

第三个列表看起来像这样

[0]
AdHeadline = "Sony Ericsson Arc silver"
MatchingFeed  = "Sony Ericsson Xperia Arc Silver"
// etc

我已经尝试遍历第一个列表并使用 Regex.Match 类,如果我找到匹配项,则填充第三个列表 - 我想知道您首选的方法是什么是的,以及如何检查分钟。表达式中有2个以上的单词。

3 个答案:

答案 0 :(得分:5)

我不确定正则表达式会给聚会带来什么。以下怎么样?

// Define a helper function to split a string into its words.
Func<string, HashSet<string>> GetWords = s =>
    new HashSet<string>(
        s.Split(new[]{' '}, StringSplitOptions.RemoveEmptyEntries)
        );

// Pair up each string with its words. Materialize the second one as
// we'll be querying it multiple times.
var aPairs = ads.Select(a => new { Full = a, Words = GetWords(a) });
var fPairs = feedItems
                 .Select(f => new { Full = f, Words = GetWords(f) })
                 .ToArray();

// For each ad, select all the feeds that match more than one word.
// Then just select the original ad and feed strings.
var result = aPairs.SelectMany(
    a => fPairs
        .Where(f => a.Words.Intersect(f.Words).Skip(1).Any())
        .Select(f => new { AdHeadline = a.Full, MatchingFeed = f.Full })
    );

答案 1 :(得分:1)

有趣的问题。您可以通过多种方式解决此问题,但可能有一个好主意是建立一个制造商列表,然后您可以使用这些制造商从传入的列表字符串中删除。然后为您关注的所有移动模型构建查找表,并在该表上使用型号和制造商(您之前已确认)进行LINQ选择。因此,确定什么是制造商和型号可能会让您更轻松。

就个人而言,我不会使用正则表达式,而是构建一个通用的手机模型类,然后您可以使用它来创建列表。此外,如果手动输入手机数据,请考虑使用Levenshtein algorithm

答案 2 :(得分:1)

肯定有更有效的方法可以做到这一点,但这里有一些事情可以让你开始。

class Program
{
    private static void Main()
    {
        var ads = new[]
        {
            "Sony Ericsson Arc silver",
            "Sony Ericsson Play R800I",
            "Oneword",
        };

        var feedItems = new[]
        {
            "Sony Ericsson Xperia Arc Silver",
            "Nokia Lumia 900",
            "Sony Ericsson Xperia Play R800i Black",
        };

        var results = from ad in ads
                      from feedItem in feedItems
                      where isMatch(ad, feedItem)
                      select new
                      {
                          AdHeadline = ad,
                          MatchingFeed = feedItem,
                      };

        foreach (var result in results)
        {
            Console.WriteLine(
                "AdHeadline = {0}, MatchingFeed = {1}",
                result.AdHeadline,
                result.MatchingFeed
            );
        }
    }

    public static bool isMatch(string ad, string feedItem)
    {
        var manufacturerWords = new[] { "sony", "ericsson", "nokia" };

        ad = ad.ToLower();
        feedItem = feedItem.ToLower();

        var adWords = Regex.Split(ad, @"\W+").Except(manufacturerWords);
        var feedItemWords = Regex.Split(feedItem, @"\W+").Except(manufacturerWords);

        var isMatch = adWords.Count(feedItemWords.Contains) >= 2;
        return isMatch;
    }
}
相关问题