【问题标题】:Check if list contains a string that matches closely检查列表是否包含紧密匹配的字符串
【发布时间】:2017-10-20 17:13:55
【问题描述】:

我正在尝试找出实现以下场景的最有效方法:

我有一个这样的列表:

public static IEnumerable<string> ValidTags = new List<string> {
  "ABC.XYZ",
  "PQR.SUB.UID",
  "PQR.ALI.OBD",
};

我有一个包含多列的巨大 CSV。其中一列是tags。此列包含空白值或上述值之一。问题是,标签列可能包含像“ABC.XYZ?@”这样的值,即有效标签加上一些无关的字符。我需要使用有效标签更新这些列,因为它们“非常匹配”我们的有效标签之一。

示例:

  • 如果 CSV 包含 PQR.ALI.OBD? 使用有效标签 PQR.ALI.OBD 更新它
  • 如果CSV包含PQR.ALI.OBA,这是无效的,只需添加后缀无效并更新它PQR.ALI.OBA-invalid

我正在尝试找出最好的方法来做到这一点。

我目前的做法是:

  1. 遍历CSV中的每一列,得到tagValue
  2. 现在检查我们的 tagValue 是否包含列表中的任何字符串
  3. 如果它包含但不完全相同,则使用它包含的值更新它。
  4. 如果它不“包含”列表中的任何值,请添加 suffix-invalid。

有没有更好/更有效的方法来做到这一点?

更新:

列表只有 5 项,我在这里展示了 3 项。 额外的字符仅在末尾,这是因为人们在 excel 网络版本中编辑这些 CSV,这会弄乱一些条目。

我当前的代码:(我确信有更好的方法来做到这一点,在 C# 中也是新的,所以请告诉我如何改进它)。我正在使用 CSVHelper 获取 CSV 单元格。

var record = csv.GetRecord<Record>();
string tag = csv.GetField(10); //tag column number in CSV is 10
/* Criteria for validation:
* tag matches our list, but has extraneous chars - strip extraneous chars and update csv
* tag doesn't match our list - add suffix invalid.*/
int listIndex = 0;
bool valid;
foreach (var validTags in ValidTags) //ValidTags is the enum above
{
    if (validTags.Contains(tag.ToUpper()) && !string.Equals(validTags, subjectIdentifier.ToUpper()))
    {
     valid = true;
     continue; //move on to next csv row.
    //this means that tag is valid but has some extra characters appended to it because of web excel, strip extra charts

    }
    listIndex++; 
    if(listIndex == 3 && !valid) { 
     //means we have reached the end of the list but not found valid tag 
     //add suffix invalid and move on to next csv row
    }
}

【问题讨论】:

  • 多余的字符总是在最后吗?
  • 这真的是列表中仅有的三个项目吗?或者任何列表项是其他列表项的子集(例如ABC.XYZABC.XYZ.PQR)?
  • 你能分享你目前的方法代码吗?
  • 我会更新这个问题的更多细节......谢谢。
  • @sniperd 这不是最好的。这是最简单的。它不将转置识别为单个操作。 Damerau Levenshtein 更好,但仍不如专门为模糊匹配编写的现代算法。 Damerau 创建于 60 年代

标签: c# regex string csv


【解决方案1】:

由于您说额外字符仅在末尾,并且假设原始标签仍然存在于额外字符之前,您可以在列表中搜索每个标签以查看该标签是否包含列表中的条目.如果是,则将其更新为正确的条目,如果它不完全匹配,如果不匹配,则将“-invalid”标记附加到它。

在执行此操作之前,我们可能需要先对列表进行降序排序,以便在搜索时找到最接近(最长)的匹配项(如果列表中的一项以列表中的另一项开头)。

var csvPath = @"f:\public\temp\temp.csv";
var entriesUpdated = 0;

// Order the list so we match on the most similar match (ABC.DEF before ABC)
var orderedTags = ValidTags.OrderByDescending(t => t);
var newFileLines = new List<string>();

// Read each line in the file
foreach (var csvLine in File.ReadLines(csvPath))
{
    // Get the columns
    var columns = csvLine.Split(',');

    // Process each column
    for (int index = 0; index < columns.Length; index++)
    {
        var column = columns[index];

        switch (index)
        {
            case 0: // tag column
                var correctTag = orderedTags.FirstOrDefault(tag =>
                    column.IndexOf(tag, StringComparison.OrdinalIgnoreCase) > -1);

                if (correctTag != null)
                {
                    // This item contains a correct tag, so 
                    // update it if it's not an exact match
                    if (column != correctTag)
                    {
                        columns[index] = correctTag;
                        entriesUpdated++;
                    }
                }
                else
                {
                    // This column does not contain a correct tag, so mark it as invalid
                    columns[index] += "-invalid";
                    entriesUpdated++;
                }

                break;

            // Other cases for other columns follow if needed
        }
    }

    newFileLines.Add(string.Join(",", columns));
}

// Write the new lines if any were changed
if (entriesUpdated > 0) File.WriteAllLines(csvPath, newFileLines);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 2019-07-30
    • 2013-01-01
    • 2017-11-20
    相关资源
    最近更新 更多