linq 是否有更好的方法(最快)来获取最长的公用文件夹路径?

yhqotfr8  于 2022-12-06  发布在  其他
关注(0)|答案(4)|浏览(164)

我有一个文件夹列表,想把最长的公共子串作为输出。
这是我的代码,看起来不是很好,
如何改善这些?
这些文件都来自我的RecursiveSearch函数,它可能是D:\123,E:\456,F:\a\e\eff,我保存到xml。
后来从xml中读回来,想得到以前的决定。
文件可能会有上万个我在乎的是速度

var li = new List<string>()
{
    @"C:\Users\jared\Desktop\fld1\eumaps\4.jfif",
    @"C:\Users\jared\Desktop\fld2\eumaps - (2)\4.jfif",
    @"C:\Users\jared\Desktop\fld4\ade\4.jfif",
    @"C:\Users\jared\Desktop\fld4\abc\S.png",
    @"C:\Users\jared\Desktop\fld1\file\Snipaste_2021-07-07_03-03-45.png",
};

//var shortest1 = li.OrderBy(name => name.Length).FirstOrDefault();
string shortest = li.Aggregate((a1, a2) => a1.Length < a2.Length ? a1 : a2);
string longest = li.Aggregate((a1, a2) => a1.Length > a2.Length ? a1 : a2);
string common = string.Concat(shortest.TakeWhile((c, i) => c == longest[i]));
// C:\Users\jared\Desktop\fld       NOT MY WANT CAUSE THERE IS NO SUCH FOLDER.

if (!Directory.Exists(common))
{
    common = common.Replace(common.Split("\\").Last(), "");
}
w6lpcovy

w6lpcovy1#

如果有任何其他路径具有不同的长度并且在中间具有不同的路径,则您的方法将失败,因为您只是比较shortestlongest
根据我的理解,您希望输出到匹配的文件夹(而不是文件夹或文件名的子字符串),即C:\Users\jared\Desktop\
这是我的解决方案,运行在O(Nk)的解决方案,其中N是路径的数量和k是最短的可用长度.
工作样本代码here
这也可以通过使用TrieData结构以更优化的方式(O(N + k))来完成,但是构建Trie需要额外的空间

var folders = new List<string>()
    {
        @"C:\Users\jared\Desktop\fld1\eumaps\4.jfif",
        @"C:\Users\jared\Desktop\fld2\eumaps - (2)\4.jfif",
        @"C:\Users\jared\Desktop\fld4\ade\4.jfif",
        @"C:\Users\jared\Desktop\fld4\abc\S.png",
        @"C:\Users\jared\Desktop\fld1\file\Snipaste_2021-07-07_03-03-45.png",
    };
    
    var minPathLength = folders.Min(x => x.Length);
    
    var maxCommonPath = new StringBuilder();
    var currentCommonPath = new StringBuilder();
    for (int i = 0; i < minPathLength; i++)
    {
        var boolAllSame = true;
        var c = folders[0][i];
        boolAllSame = folders.All(x => x[i] == c);
        
        if (boolAllSame)
        {
            currentCommonPath.Append(c);
            if (c == '\\')
            {
                maxCommonPath.Append(currentCommonPath.ToString());
                currentCommonPath = new StringBuilder();
            }
        }
        else
            break;
    }
    
    var result = maxCommonPath.ToString();
    Console.WriteLine(result);
woobm2wo

woobm2wo2#

下面是一个使用Linq的简洁但性能不高的实现。对于Transpose操作符,它还依赖于MoreLinq包:

var paths = new List<string>()
{
    @"C:\Users\jared\Desktop\fld1\eumaps\4.jfif",
    @"C:\Users\jared\Desktop\fld2\eumaps - (2)\4.jfif",
    @"C:\Users\jared\Desktop\fld4\ade\4.jfif",
    @"C:\Users\jared\Desktop\fld4\abc\S.png",
    @"C:\Users\jared\Desktop\fld1\file\Snipaste_2021-07-07_03-03-45.png",
};
string[] longestCommonPathComponents = paths
    .Select(path => path.Split(Path.DirectorySeparatorChar))
    .Transpose()
    .Select(parts => parts.Distinct(StringComparer.OrdinalIgnoreCase))
    .TakeWhile(distinct => distinct.Count() == 1)
    .Select(distinct => distinct.First())
    .ToArray();
string longestCommonPath = Path.Combine(longestCommonPathComponents);
Console.WriteLine($"Longest common path: {longestCommonPath}");

输出量:
最长公共路径:C:/用户/jared/桌面
Try it on fiddle中的一个。
Transpose运算符的签名:

// Transposes a sequence of rows into a sequence of columns.
public static IEnumerable<IEnumerable<T>> Transpose<T>(
    this IEnumerable<IEnumerable<T>> source);
qacovj5a

qacovj5a3#

var li = new List<string>()
{
    @"C:\Users\jared\Desktop\fld1\eumaps\4.jfif",
    @"C:\Users\jared\Desktop\fld2\eumaps - (2)\4.jfif",
    @"C:\Users\jared\Desktop\fld4\ade\4.jfif",
    @"C:\Users\jared\Desktop\fld4\abc\S.png",
    @"C:\Users\jared\Desktop\fld1\file\Snipaste_2021-07-07_03-03-45.png",
};

string first = li.First();
int n = 0;

while (li.All(x => x.Length > n && x[n] == first[n]))
    n++;

string longestCommon = first.Substring(0, n); // C:\Users\jared\Desktop\fld

你说C:\Users\jared\Desktop\fld不是你想要的,但是你想要什么呢?最嵌套的有效文件夹吗?只要拉到最后一个斜杠,或者使用Path方法得到你想要的位。

o4tp2gmn

o4tp2gmn4#

建议:为图像路径使用以下代码

var li = new List<string>()
{
Application.StartupPath + "/Images/1.png",
Application.StartupPath + "/Images/2.png",
Application.StartupPath + "/Images/3.png",
}

相关问题