匹配两个列表

时间:2010-12-24 22:59:34

标签: c# .net search

我有一张包含人类输入观察数据的表格。有一列应该与另一个列表相对应;人类输入的值应该与某种主要可能性列表中的值相同。

然而问题是人类数据是缩写,拼写错误等等。是否有一种机制可以进行某种相似性搜索,以找出人类输入的数据应该是什么?

实施例

**Human Entered**         **Should Be**
Carbon-12                 Carbon(12)
South Korea               Republic of Korea
farenheit                 Fahrenheit

我唯一想到的就是将人类输入的数据分解成3个字符的部分,看看它们是否包含在“应该是”列表中。它只会选择评分最高的条目。作为后来的添加,它可以向用户提供前10名或其他内容的选择。

我也不一定对一个绝对完美的解决方案感兴趣,但是如果它的效果好70%就可以节省很多时间。

3 个答案:

答案 0 :(得分:3)

一种选择是在两个字符串之间寻找一个小Levenshtein distance,而不是要求完全匹配。这有助于找到存在轻微拼写差异或拼写错误的匹配。

另一种选择是在比较它们之前规范化字符串。有意义的规范化技术取决于您的具体应用,但它可能涉及:

  • 删除所有标点符号。
  • 将英国拼写转换为美国拼写。
  • 使用物质的科学名称而不是通用名称。

然后,您可以比较每个列表的成员的规范化形式,而不是原始形式。您可能还需要考虑使用不区分大小写的比较而不是区分大小写的比较。

答案 1 :(得分:2)

您可以尝试使用Levenshtein distance计算两个字符串的相似度:

private static int CalcLevensteinDistance(string left, string right)
{
    if (left == right)
        return 0;

    int[,] matrix = new int[left.Length + 1, right.Length + 1];

    for (int i = 0; i <= left.Length; i++)
        // delete
        matrix[i, 0] = i;

    for (int j = 0; j <= right.Length; j++)
        // insert
        matrix[0, j] = j;

    for (int i = 0; i < left.Length; i++)
    {
        for (int j = 0; j < right.Length; j++)
        {
            if (left[i] == right[j])
                matrix[i + 1, j + 1] = matrix[i, j];
            else
            {
                // deletion or insertion
                matrix[i + 1, j + 1] = System.Math.Min(matrix[i, j + 1] + 1, matrix[i + 1, j] + 1);

                // substitution
                matrix[i + 1, j + 1] = System.Math.Min(matrix[i + 1, j + 1], matrix[i, j] + 1);
            }
        }
    }

    return matrix[left.Length, right.Length];
}

现在计算%

中两个字符串之间的相似度
public static double CalcSimilarity(string left, string right, bool ignoreCase)
{
    if (ignoreCase)
    {
        left = left.ToLower();
        right = right.ToLower();
    }

    double distance = CalcLevensteinDistance(left, right);
    if (distance == 0.0f)
        return 1.0f;

    double longestStringSize = System.Math.Max(left.Length, right.Length);
    double percent = distance / longestStringSize;

    return 1.0f - percent;
}

答案 2 :(得分:1)

您是否考虑使用(...或多个)下拉列表来强制执行正确的输入?在我看来,在考虑可用性和用户友好性的情况下,这在大多数情况下是更好的方法。它还可以使这一输入的处理变得更加容易。当只使用自由文本输入时,你可能会有很多不同的方法来编写一个东西,而你“永远不会”能够找出编写任何复杂内容的方法。

示例:正如您所写; “碳-12”,“碳12”,“碳(12)”,“碳(12)”,“碳-12”等......就此而言,可能性几乎是无穷无尽的。当你还考虑像“韩国”和“韩国”这样的地图,其映射不是“1:1”(朝鲜怎么样?或者只是“韩国”?),这变得更加困难。

当然,我对你的申请一无所知,可能完全错了。但通常情况下,当您期望某种格式的复杂值时,下拉列表在很多情况下会使您作为开发人员的工作变得更容易,并为最终用户提供更好的体验。