【问题标题】:Get the more similar string from a list从列表中获取更相似的字符串
【发布时间】:2015-12-19 13:50:06
【问题描述】:

我有一个List,其中包含我需要的所有远程路径

List<string> remotePath = MyTableWithRemotePath.Select(i => i.ID_SERVER_PATH).ToList();

我有一个字符串,它是我要查找的服务器。

string remotePath = "Path I'm looking for";

我必须找到与我要查找的路径更匹配的列表路径。

我试过了,但它不起作用

var matchingvalues = remotePath.FirstOrDefault(stringToCheck => stringToCheck.Contains(remotePath));

有什么建议吗?

编辑

例子:

我必须找到这条路径的最佳匹配:C:\\something\\location\\

这是我的清单:

- C:\\something\\location\\XX\\
- C:\\something\\location2\\YY\\
- C:\\something\\location3\\AA\\
- C:\\something\\location4\\CS\\

结果必须是第一个元素:

C:\\something\\location\\directory\\

【问题讨论】:

  • 你能解释一下“更好的匹配”吗?可以举一些例子吗?
  • “我必须找到与我正在寻找的路径更匹配的列表路径”是什么意思。您是否只是想对您的字符串进行部分匹配,寻找具有最匹配字符的内容?如果是这样,也许您可​​以将 PathImLookingFor 分解为单独的目录,并在列表中查找包含这些目录的项目,按照匹配最多到最少的顺序。
  • @sab669 完全正确。就是这样
  • 您的意思是像 SQL LIKE 运算符?或者更像谷歌的东西,如果你输入foopd,就会找到food?
  • @Thomas 取 3 个字符串:前两个是我们正在检查的字符串,第三个字符串是我们想要找到最接近匹配的字符串。 "C:\some\directory\is\here\"、"C:\some\directory\over\here" 是 remotePath 中的两个值。 "\directory\is\" 是我们想要找到最接近匹配的字符串。因此,虽然前两个字符串在其路径中都包含 directory,但第一个是“更好的匹配”,因为它包含更多匹配的目录。

标签: c# string linq


【解决方案1】:

最后我以这种方式做到了并且完美地工作:

    var bestPath  = remotePaths.OrderByDescending(i => i.ID_FILE_PATH.Length)
                               .ToList()
                               .FirstOrDefault(i => rootPath.StartsWith(i.ID_FILE_PATH, StringComparison.InvariantCultureIgnoreCase));

【讨论】:

  • ToList 是多余的。
  • @TimSchmelter 不,没有 ToList() 我得到了异常。
  • 如您所说,如果 remotePaths 是 List&lt;string&gt; 则不可能。但是由于string 没有属性ID_FILE_PATH 它一定是不同的东西。我猜它是一个数据库对象,linq 提供程序不支持StartsWith 过载StringComparison。这就是您从所有记录中创建内存中List&lt;t&gt; 的原因。我希望你有足够的内存。您可以改用rootPath.ToUpper().StartsWith(i.ID_FILE_PATH.ToUpper())。
【解决方案2】:
var remotePaths = new List<string>
{
    @"C:\something\location\directory\",
    @"C:\something\location2\directory\",
    @"C:\something\location3\directory\",
    @"C:\something\location4\directory\"
};

var remotePath = @"C:\something\location\directory\";


var result = remotePaths
    .Select(p => new { p, mathes = p.Split('\\').TakeWhile((x, i) => x == remotePath.Split('\\')[i]).Count()})
    .OrderByDescending(p => p.mathes)
    .First().p;

结果:

C:\something\location\directory\

代码遍历每个目录创建解析它并为每个目录创建子目录,然后将每个子目录与 remotePath 子目录进行比较。最后,它会选择匹配次数最多的第一个。

【讨论】:

  • 相同匹配是什么意思。代码准确地返回您在问题中提出的内容。你能详细说明一下到底是什么不起作用吗?
【解决方案3】:

我会说:

string dir = @"some\\path\\im\\looking\\for";

将其分解为每个路径的数组。

string[] dirs = new string[n] { "some", "path", "im", "looking", "for" };

然后遍历您的列表,同时检查数组中的每个项目。每次匹配时,将其添加到具有键(完整路径)和值(匹配数)的另一个集合中。

for (int i = 0; i < remotePath.Count; i++)
{
    int counter = 0;

    for (int j = 0; j < dirs.Length; j++)
    {
        if (remotePath[i].Contains(dirs[j])
            counter++;
    }

    if (counter > 0)
        someStringIntDictionary.Add(remotePath[i], counter);
}

关于确定哪个是“最佳匹配”的最终任务,老实说,我不确定具体该怎么做,但在 Google 上搜索 C# find dicitonary key with highest value 给了我这个:

https://stackoverflow.com/a/2806074/1189566

这个答案可能不是最有效的,在多个集合上嵌套循环,但它应该可以工作。

我想指出,如果文件名或子目录与 dirs 中的某些内容共享名称的一部分,这可能会导致不准确。因此,使用数组中的第一项 "some",您可能会遇到以下情况的错误:

"C:\\something\\location\\directory\\flibflam\\file.pdf"

something 会错误地匹配 some,因此它实际上可能不是有效匹配。您可能需要检查实际路径中与目录相邻的字符,并确保它们是 \ 字符。

【讨论】:

    猜你喜欢
    • 2020-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    • 2012-01-12
    • 1970-01-01
    相关资源
    最近更新 更多