我得到了一个文件和目录列表List<string> pathes
。现在我想计算每条路径彼此共享的最深的公共分支。
我们可以假设它们都有共同的路径,但这在开始时是未知的。
假设我有以下三个条目:
这应该得到结果:C:/ Hello /因为地球正在打破子目录的这个“链”。
第二个例子:
- &GT; C:/你好/世界/这/是/
你会怎么做?我尝试使用string.split(@“/”)并从第一个字符串开始,并检查此数组的每个部分是否包含在其他字符串中。但是,这将是一个非常昂贵的调用,因为我正在迭代(list_of_entries)^ list_of_entries。有没有更好的解决方案?
我目前的尝试类似于以下内容(C#+ LINQ):
public string CalculateCommonPath(IEnumerable<string> paths)
{
int minSlash = int.MaxValue;
string minPath = null;
foreach (var path in paths)
{
int splits = path.Split('\\').Count();
if (minSlash > splits)
{
minSlash = splits;
minPath = path;
}
}
if (minPath != null)
{
string[] splits = minPath.Split('\\');
for (int i = 0; i < minSlash; i++)
{
if (paths.Any(x => !x.StartsWith(splits[i])))
{
return i >= 0 ? splits.Take(i).ToString() : "";
}
}
}
return minPath;
}
答案 0 :(得分:5)
获取最长公共前缀的函数可能如下所示:
public static string GetLongestCommonPrefix(string[] s)
{
int k = s[0].Length;
for (int i = 1; i < s.Length; i++)
{
k = Math.Min(k, s[i].Length);
for (int j = 0; j < k; j++)
if (s[i][j] != s[0][j])
{
k = j;
break;
}
}
return s[0].Substring(0, k);
}
然后你可能需要在右边剪切前缀。例如。我们想要返回c:/dir
而不是c:/dir/file
c:/dir/file1
c:/dir/file2
您还可能希望在处理之前规范化路径。请参阅Normalize directory names in C#。
答案 1 :(得分:5)
我不知道这是否是性能最佳的解决方案(可能不是),但它确实很容易实现。
示例代码:
List<string> paths = new List<string>();
paths.Add(@"C:/Hello/World/This/Is/An/Example/Bla.cs");
paths.Add(@"C:/Hello/World/This/Is/Not/An/Example/");
paths.Add(@"C:/Hello/Earth/Bla/Bla/Bla");
List<string> sortedPaths = paths.OrderBy(s => s).ToList();
Console.WriteLine("Most common path here: {0}", sharedSubstring(sortedPaths[0], sortedPaths[sortedPaths.Count - 1]));
当然这个功能:
public static string sharedSubstring(string string1, string string2)
{
string ret = string.Empty;
int index = 1;
while (string1.Substring(0, index) == string2.Substring(0, index))
{
ret = string1.Substring(0, index);
index++;
}
return ret;
} // returns an empty string if no common characters where found
答案 2 :(得分:1)
我会迭代第一条路径中的每个字符,将它与路径集合中每条路径(第一条路径除外)中的每个字符进行比较:
public string FindCommonPath(List<string> paths)
{
string firstPath = paths[0];
bool same = true;
int i = 0;
string commonPath = string.Empty;
while (same && i < firstPath.Length)
{
for (int p = 1; p < paths.Count && same; p++)
{
same = firstPath[i] == paths[p][i];
}
if (same)
{
commonPath += firstPath[i];
}
i++;
}
return commonPath;
}
您可以先遍历列表,找到最短路径,然后稍微改进一下。
答案 3 :(得分:1)
首先使用要检查的路径对列表进行排序。然后您可以拆分并比较第一个和最后一个项目 - 如果它们相同则继续下一个维度,直到找到差异为止。
所以你只需要排序一次,然后检查两个项目。
答案 4 :(得分:0)
为
返回componentDidUpdate(){
this.canvasFabric.setWidth(this.state.width);
}
c:/dir
我会这样编码:
c:/dir/file1
c:/dir/file2
这是一些测试:
public static string GetLongestCommonPrefix(params string[] s)
{
return GetLongestCommonPrefix((ICollection<string>)s);
}
public static string GetLongestCommonPrefix(ICollection<string> paths)
{
if (paths == null || paths.Count == 0)
return null;
if (paths.Count == 1)
return paths.First();
var allSplittedPaths = paths.Select(p => p.Split('\\')).ToList();
var min = allSplittedPaths.Min(a => a.Length);
var i = 0;
for (i = 0; i < min; i++)
{
var reference = allSplittedPaths[0][i];
if (allSplittedPaths.Any(a => !string.Equals(a[i], reference, StringComparison.OrdinalIgnoreCase)))
{
break;
}
}
return string.Join("\\", allSplittedPaths[0].Take(i));
}
答案 5 :(得分:0)
该功能可为您提供最长的公用目录路径,并具有最佳的复杂性:
d3.scaleLinear