none
Linq based sorting and grouping RRS feed

  • Question

  • I am recursively enumerating a directory for all its files and its expected that the base path contains nested directories each with files. I need to construct a nested XML hierarchy with additional meta data using linq to xml in a format that must also resemble the file system layout. For example the following structure:
    Base-Directory\
      |- Sub-Directory-0\
         |- Sub-Directory-1\
            |- file-4
            |- file-5
         |- file-2
         |- file-3
      |- File-0
      |- File-1
    Should resemble:
    <root>
      <dir id="Sub-Directory-0" path="Base-Directory\Sub-Directory-0">
        <dir id="Sub-Directory-1" path="Base-Directory\Sub-Directory-0\Sub-Directory-1">
          <file id="File-4" path="Base-Directory\Sub-Directory-0\Sub-Directory-1\File-4" />
          <file id="File-5" path="Base-Directory\Sub-Directory-0\Sub-Directory-1\File-5" />
        </dir>
        <file id="File-2" path="Base-Directory\File-2" />
        <file id="File-3" path="Base-Directory\File-3" />
      </dir>
      <file id="File-0" path="Base-Directory\File-0" />
      <file id="File-1" path="Base-Directory\File-1" />
    </root>
    My thoughts were to split the paths I obtain on slashes and group by array length, then group by equivalent values in each position from 0 forward to the max length of the array.

    Does a linq approach exist for this, or do I need to manually sort this?

    Thanks.
    Thursday, October 5, 2017 4:07 PM

Answers

  • Hi Ritmo2k,

    Thank you for posting here.

    For your question, here is a simple to sort without linq. Please try the following code.

    private static FileStream fs;
            private static StreamWriter sw;
    
            static void Main(string[] args)
            {
                string path;
                int leval = 0;
    
                Console.WriteLine("Please input path:");
                path = Console.ReadLine();
                path.Replace('\\', '/');
    
                fs = new FileStream("result.txt", FileMode.Create);
                sw = new StreamWriter(fs);
    
                sw.WriteLine("result:");
                sw.WriteLine(path);
    
                listDirectory(path, leval);
                sw.Flush();
                sw.Close();
                fs.Close();
                Console.WriteLine("Please input any key to continue");
                Console.ReadKey();
            }
    
            private static void listDirectory(string path, int leval)
            {
                DirectoryInfo theFolder = new DirectoryInfo(@path);
    
                leval++;
    
                //foreach files
                //foreach (FileInfo NextFile in theFolder.GetFiles())
                //{
                //    for (int i = 0; i < leval; i++) sw.Write('\t');
                //    sw.Write("-->");
                //    sw.WriteLine(NextFile.Name);
                //}
    
                //foreach folders
                foreach (DirectoryInfo NextFolder in theFolder.GetDirectories())
                {
                    for (int i = 0; i < leval; i++) sw.Write('\t');
                    sw.Write("|-");
                    sw.WriteLine("id:" + NextFolder.Name + "path:" + NextFolder.FullName);
                    listDirectory(NextFolder.FullName, leval);
                }
            }
    

    And then, here is the result.

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Proposed as answer by Fei HuModerator Wednesday, October 11, 2017 11:33 AM
    • Marked as answer by Ritmo2k Wednesday, October 11, 2017 11:54 AM
    Monday, October 9, 2017 8:10 AM
    Moderator

All replies

  • Hi Ritmo2k,

    Thank you for posting here.

    For your question, here is a simple to sort without linq. Please try the following code.

    private static FileStream fs;
            private static StreamWriter sw;
    
            static void Main(string[] args)
            {
                string path;
                int leval = 0;
    
                Console.WriteLine("Please input path:");
                path = Console.ReadLine();
                path.Replace('\\', '/');
    
                fs = new FileStream("result.txt", FileMode.Create);
                sw = new StreamWriter(fs);
    
                sw.WriteLine("result:");
                sw.WriteLine(path);
    
                listDirectory(path, leval);
                sw.Flush();
                sw.Close();
                fs.Close();
                Console.WriteLine("Please input any key to continue");
                Console.ReadKey();
            }
    
            private static void listDirectory(string path, int leval)
            {
                DirectoryInfo theFolder = new DirectoryInfo(@path);
    
                leval++;
    
                //foreach files
                //foreach (FileInfo NextFile in theFolder.GetFiles())
                //{
                //    for (int i = 0; i < leval; i++) sw.Write('\t');
                //    sw.Write("-->");
                //    sw.WriteLine(NextFile.Name);
                //}
    
                //foreach folders
                foreach (DirectoryInfo NextFolder in theFolder.GetDirectories())
                {
                    for (int i = 0; i < leval; i++) sw.Write('\t');
                    sw.Write("|-");
                    sw.WriteLine("id:" + NextFolder.Name + "path:" + NextFolder.FullName);
                    listDirectory(NextFolder.FullName, leval);
                }
            }
    

    And then, here is the result.

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Proposed as answer by Fei HuModerator Wednesday, October 11, 2017 11:33 AM
    • Marked as answer by Ritmo2k Wednesday, October 11, 2017 11:54 AM
    Monday, October 9, 2017 8:10 AM
    Moderator
  • I arrived at roughly the same approach. After looking more closely at the task, I could not consume the input in string form and know if the first listings where sub directories or files. The task required an implementation at the point of file and directory enumeration, making it tail recursive solved the issue. Something along the lines of:
    private IEnumerable<XElement> Method(string path)
    {
        foreach (string filePath in Directory.EnumerateFiles(path))
        {
            yield return new XElement(...);
        }
    
        foreach (string directory in Directory.EnumerateDirectories(path))
        {
            yield return XElement(..., content: this.Method(directory));
        }
    }

    Wednesday, October 11, 2017 12:54 PM