我有一个案例,我有一个对象的名称和一堆文件名.我需要将正确的文件名与对象匹配.文件名可以包含数字和单词,用连字符( – )或下划线(_)分隔.我无法控制文件名或对象名.例如:
10-11-12_001_002_003_13001_13002_this_is_an_example.svg
在这种情况下,对象名称只是一个字符串,表示一个数字
10001
如果文件名与对象名匹配,我需要返回true或false.文件名的不同段可以单独匹配,也可以两个段的任意组合匹配.在上面的例子中,对于以下情况应该是这样(并非每个真实情况,只是示例):
10001 10002 10003 11001 11002 11003 12001 12002 12003 13001 13002
并且,我们应该为这个案例(其中包括)返回false:
13003
到目前为止我想出的是:
public bool IsMatch(string filename,string objectname) { var namesegments = GetNameSegments(filename); var match = namesegments.Contains(objectname); return match; } public static List<string> GetNameSegments(string filename) { var segments = filename.Split('_','-').ToList(); var newSegments = new List<string>(); foreach (var segment in segments) { foreach (var segment2 in segments) { if (segment == segment2) continue; var newToken = segment + segment2; newSegments.Add(newToken); } } return segments.Concat(newSegments).ToList(); }
组合的一个或两个段可以匹配,这是必要的.不应考虑三个或更多个组合.
到目前为止这确实有效,但是有没有更好的方法来实现它,也许没有嵌套foreach循环?
解决方法
效率在很大程度上取决于您尝试解决的业务问题.在不了解完整的上下文/使用情况的情况下,很难定义最有效的解决方案.对一种情况有效的方法并不总是适用于其他情况.
我总是主张编写工作代码,然后解决任何性能问题(或者通常会更便宜!)如果你遇到特定的性能问题,那么请告诉我们更多……
我将在这里发表一篇文章并说(希望)你每次执行时只会将文件名与对象名称匹配一次.如果是这种情况,我认为这种方法将是最快的.在您将单个文件名与多个对象名称进行匹配的情况下,显而易见的选择是建立一个排序索引并与您正在进行的匹配,尽管我会根据您的预期考虑不同类型的集合执行/使用.
public static bool IsMatch(string filename,string objectName) { var segments = filename.Split('-','_'); for (int i = 0; i < segments.Length; i++) { if (string.Equals(segments[i],objectName)) return true; for (int ii = 0; ii < segments.Length; ii++) { if (ii == i) continue; if (string.Equals($"{segments[i]}{segments[ii]}",objectName)) return true; } } return false; }