2

I'm trying to group the strings according to their extension (last three characters) to train my LINQ skills (I'm a newbie), but I keep getting an exception:

System.ArgumentOutOfRangeException: 'Index and length must refer to a location within the string.

My code is bellow: Where is my mistake?

string[] files = new string[10] {"OKO.pdf","aaa.frx", "bbb.TXT", "xyz.dbf","abc.pdf", "aaaa.PDF","xyz.frt", "abc.xml", "ccc.txt", "zzz.txt"};

var res = from file in files
    group file by file.Substring(file.IndexOf(".")+1,file.Length-1) into extensions
    select extensions;

var res1 = files.GroupBy(file => file.Substring(file.IndexOf("."), file.Length - 1));

foreach(var group in res)
{
    Console.WriteLine("There are {0} files with the {1} extension.", group.Count(), group.Key);
}
Selim Yildiz
  • 5,254
  • 6
  • 18
  • 28
NanoTech
  • 135
  • 1
  • 6
  • 4
    From : file.Substring(file.IndexOf(".")+1,file.Length-1) To : file.Substring(file.IndexOf(".")+1) – jdweng Jan 14 '20 at 17:58
  • Thanks, it was real simple. I'm used to substring methods that accept range and not length – NanoTech Jan 14 '20 at 18:00
  • https://stackoverflow.com/questions/1886866/how-to-find-the-extension-of-a-file-in-c – Alexei Levenkov Jan 14 '20 at 18:02
  • To clarify @jdweng's correct answer - the signature of the two-parameter substring method is `String.Substring(int startIndex, int length)`, so your out of range exception is because you're trying to get a substring with length equal to the length of the string-1, starting from the character after the '.' - the `String.Substring(int startIndex)` method returns the substring from the specified index to the end of the string – Zaelin Goodman Jan 14 '20 at 18:04

2 Answers2

3

As jdweng mentioned on comment section. You just need to use overload of Substring

The substring starts at a specified character position and continues to the end of the string.

string[] files = new string[10] { "OKO.pdf", "aaa.frx", "bbb.TXT", "xyz.dbf", "abc.pdf", "aaaa.PDF", "xyz.frt", "abc.xml", "ccc.txt", "zzz.txt" };

var res = from file in files
          group file by file.Substring(file.IndexOf(".") + 1) into extensions
          select extensions;

foreach (var group in res)
{
    Console.WriteLine("There are {0} files with the {1} extension.", group.Count(), group.Key);
}

Result would be:

There are 2 files with the pdf extension.
There are 1 files with the frx extension.
There are 1 files with the TXT extension.
There are 1 files with the dbf extension.
There are 1 files with the PDF extension.
There are 1 files with the frt extension.
There are 1 files with the xml extension.
There are 2 files with the txt extension
Selim Yildiz
  • 5,254
  • 6
  • 18
  • 28
2

As your filenames can contain dots, the position of dot can be incorrect if you use IndexOf. You can use Split method to solve this problem (note that there's a file with a dot OKO.ZOKO.pdf and see the output):

static void other()
{
    var names = new[] { "OKO.pdf", "OKO.ZOKO.pdf", "aaa.frx", "bbb.TXT", "xyz.dbf", "abc.pdf" };
    var x = names.GroupBy(n => n.Split('.').Last());
    x.ToList().ForEach(g => WriteLine($"There are {g.Count()} files with extension '{g.Key}'"));
}

// Output:
//    There are 3 files with extension 'pdf'
//    There are 1 files with extension 'frx'
//    There are 1 files with extension 'TXT'
//    There are 1 files with extension 'dbf'
JohnyL
  • 6,894
  • 3
  • 22
  • 41