动态正则表达式生成,用于数据馈送中可预测的重复字符串模式

2024-03-13

我目前正在尝试处理一些我无法控制的数据源,其中我使用 C# 中的正则表达式来提取信息。

数据源的发起者从数据库中提取基本行数据(如产品名称、价格等),然后在英文文本行中格式化该数据。对于每一行,一些文本是重复的静态文本,一些是从数据库动态生成的文本。

e.g

带免费蓝光播放器的松下电视

索尼电视带免费 DVD 播放器 + 票房 DVD

Kenwood Hi-Fi 设备含 20 美元 Amazon MP3 优惠券

所以本例中的格式是:PRODUCT with FREEGIFT.

PRODUCT and FREEGIFT是每行的动态部分,“with”文本是静态的。每个 feed 大约有 2000 行。

创建正则表达式来提取动态部分很简单。

问题是控制数据源的营销机构不断改变静态文本的结构,通常每两周一次,所以本周我可能会:

如果您今天订购,全新松下电视和免费蓝光播放器

全新索尼电视和免费 DVD 播放器 + 票房 DVD(如果您今天订购)

全新 Kenwood Hi-Fi 设备,如果您今天订购,还可获赠价值 20 美元的 Amazon MP3 优惠券

下周可能会有所不同,所以我必须继续修改我的正则表达式......

你会如何处理这个问题?

是否有一种算法可以确定重复字符串行中的静态和可变文本?如果是这样,使用此类算法的输出以编程方式创建动态正则表达式的最佳方法是什么?

感谢您的任何帮助或建议。


这段代码并不完美,当然也效率不高,但是很可能来不及帮助你了,但它确实有效。如果给定一组字符串,它将返回超过一定长度的公共内容。

然而,正如其他人所提到的,算法只能给您一个近似值,因为您可能会遇到一个错误的批次,其中所有产品都具有相同的初始单词,然后代码会意外地将该内容识别为静态。当动态内容与静态内容共享值时,它也可能会产生不匹配,但随着输入的样本大小的增加,出错的可能性将会缩小。

我建议在数据的子集上运行它(20000 行将是一个坏主意!)并进行某种额外的健全性检查(静态元素的最大数量等)

最后的警告:它可能做得很完美,但即使它做到了,你怎么知道哪个项目是PRODUCT哪一个是FREEGIFT?

算法

  1. 如果集合中的所有字符串都以相同的字符开头,则将该字符添加到“当前匹配”集合中,然后从所有字符串中删除前导字符
  2. 如果不是,则从第一个字符的所有字符串中删除第一个字符x(最小匹配长度)字符不包含在所有其他字符串中
  3. 一旦出现不匹配(情况 2),如果满足长度要求,则生成当前匹配
  4. 继续,直到所有字符串都用完

实施情况

private static IEnumerable<string> FindCommonContent(string[] strings, int minimumMatchLength)
{
    string sharedContent = "";

    while (strings.All(x => x.Length > 0))
    {
        var item1FirstCharacter = strings[0][0];

        if (strings.All(x => x[0] == item1FirstCharacter))
        {
            sharedContent += item1FirstCharacter;

            for (int index = 0; index < strings.Length; index++)
                strings[index] = strings[index].Substring(1);

            continue;
        }

        if (sharedContent.Length >= minimumMatchLength)
            yield return sharedContent;

        sharedContent = "";

        // If the first minMatch characters of a string aren't in all the other strings, consume the first character of that string
        for (int index = 0; index < strings.Length; index++)
        {
            string testBlock = strings[index].Substring(0, Math.Min(minimumMatchLength, strings[index].Length));

            if (!strings.All(x => x.Contains(testBlock)))
                strings[index] = strings[index].Substring(1);
        }
    }

    if (sharedContent.Length >= minimumMatchLength)
        yield return sharedContent;
}

Output

设置 1(来自您的示例):

FindCommonContent(strings, 4);
=> "with "

设置 2(来自您的示例):

FindCommonContent(strings, 4);
=> "Brand new ", "and a ", "if you order today"

构建正则表达式

这应该很简单:

 "{.*}" + string.Join("{.*}", FindCommonContent(strings, 4)) + "{.*}";
=> "^{.*}Brand new {.*}and a {.*}if you order today{.*}$"

尽管您可以修改算法以返回有关匹配位置的信息(在静态内容之间或之外),但这没问题,因为您知道有些匹配无论如何都会匹配零长度字符串。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

动态正则表达式生成,用于数据馈送中可预测的重复字符串模式 的相关文章

随机推荐