how to extract common file path from list of file paths in c#

后端 未结 9 1451
粉色の甜心
粉色の甜心 2021-01-17 15:42

What is the best way extract the common file path from the list of file path strings in c#?

Eg: I have a list 5 file paths in List variable, like below

c:\

相关标签:
9条回答
  • 2021-01-17 16:07

    The top answer fails for identical paths like e.g.:

    string str1 = @"c:\dir\dir1\dir2\dir3";
    string str2 = @"c:\dir\dir1\dir2\dir3";
    

    This is better: Find common prefix of strings

    however

    .TakeWhile(s => s.All(d => d == s.First()))
    

    should be

    .TakeWhile(s =>
          {
              var reference = s.First();
              return s.All(d => string.Equals(reference, d, StringComparison.OrdinalIgnoreCase));
          })
    
    0 讨论(0)
  • 2021-01-17 16:13

    You could break the paths down into segments (i.e. split by the backslash), then build back a segment at a time and compare the results until you find the end of the match. I doubt that is the best way, but it would work.

    0 讨论(0)
  • 2021-01-17 16:14

    Use the first path as the iterator seed:

    using System;
    using System.Collections.Generic;
    using System.IO;
    
    namespace stackoverflow1
    {
        class MainClass
        {
            public static void Main (string[] args)
            {
                List<String> paths=new List<String>();
                paths.Add(@"c:\abc\pqr\tmp\sample\b.txt");
                paths.Add(@"c:\abc\pqr\tmp\new2\c1.txt");
                paths.Add(@"c:\abc\pqr\tmp\b2.txt");
                paths.Add(@"c:\abc\pqr\tmp\b3.txt");
                paths.Add(@"c:\abc\pqr\tmp\tmp2\b2.txt");
    
                Console.WriteLine("Found: "+ShortestCommonPath(paths));
    
            }
    
            private static String ShortestCommonPath(IList<String> list)
            {
                switch (list.Count)
                {
                case 0: return null;
                case 1: return list[0];
                default:
                    String s=list[0];
                    while (s.Length>0)
                    {
                        bool ok=true;
                        for (int i=1;i<list.Count;i++)
                        {
                            if (!list[i].StartsWith(s))
                            {
                                ok=false;
                                int p=s.LastIndexOf(Path.DirectorySeparatorChar);
                                if (p<0) return "";
                                s=s.Substring(0,p);
                                break;
                            }
                        }
                        if (ok) break;
                    }
                    return s;
                }
            }
    
        }
    }
    
    0 讨论(0)
  • 2021-01-17 16:18

    I don't think there's a "trick"to get past using the brute force method to do this comparison, but you can optimize your solution somewhat:

    Prepare:
    Find the shortest string
    
    Repeat:
    See if all of the other strings contain it
    If so, you're done
    If not, remove one or more characters
    
    0 讨论(0)
  • 2021-01-17 16:20

    I would use a loop and on each string I'd split it with s.Split('\').

    Then it iterate over the first element, and next element, saving them as I go.

    When I find one that is different, I can return the last iteration's result.

    string commonPath(string[] paths) {
        // this is a Java notation, I hope it's right in C# as well? Let me know!
        string[][] tokens = new string[paths.length][];
    
        for(int i = 0; i < paths.Length; i++) {
            tokens[i] = paths.Split('\\');
        }
    
        string path = "";
    
        for(int i = 0; i < tokens[0].Length; i++) {
            string current = tokens[0][i];
            for(int j = 1; j < tokens.Length; j++) {
                if(j >= tokens[i].Length) return path;
                if(current != tokens[i][j]) return path;
            }
            path = path + current + '\\';
        }
        return path; // shouldn't reach here, but possible on corner cases
    }
    
    0 讨论(0)
  • 2021-01-17 16:23

    Here is a quick implementation that just loops through the list of strings and then compares the characters at the beginning of the strings trimming from the original string:

    List<string> list1 = new List<string>();
    list1.Add(@"c:\abc\pqr\tmp\sample\b.txt");
    list1.Add(@"c:\abc\pqr\tmp\new2\c1.txt");
    list1.Add(@"c:\abc\pqr\tmp\b2.txt");
    list1.Add(@"c:\abc\pqr\tmp\b3.txt");
    list1.Add(@"c:\abc\pqr\tmp\tmp2\b2.txt");
    
    string baseDir = "";
    foreach (var item in list1)
    {
        if (baseDir == "")
            baseDir = System.IO.Path.GetDirectoryName(item);
        else
        {
            int index = 0;
            string nextDir = System.IO.Path.GetDirectoryName(item);
            while (index< baseDir.Length && index<nextDir.Length && 
                baseDir[index] == nextDir[index])
            {
                index++;
            }
            baseDir = baseDir.Substring(0, index);
        }
    }
    MessageBox.Show(baseDir);
    
    0 讨论(0)
提交回复
热议问题