I have an array (text file) of 1000 lines, separated by commas, here is an example of lines:

**#,LM,Jam ID,Date Occurred,Time Jammed,Rc,Rt,Cl,Jam Text** 001,03,043,04/07/15 16:02,00:00:25,00,00,00,Indexer #1 shot pin state is unknown 002,02,030,09/24/15 16:39,00:00:04,00,00,01,ATT unable to detect tray at Gripper 003,01,044,09/24/15 16:38,00:00:25,00,00,01,Main tray is hanging on guides or stuck in gripper. 004,01,044,09/24/15 16:36,00:01:51,00,01,00,Main tray is hanging on guides or stuck in gripper. 005,02,030,09/24/15 15:11,00:00:04,00,00,01,ATT unable to detect tray at Gripper 006,01,044,09/24/15 15:10,00:00:27,00,01,00,Main tray is hanging on guides or stuck in gripper. 007,01,044,09/24/15 15:10,00:00:21,00,01,00,Main tray is hanging on guides or stuck in gripper. 008,02,030,09/21/15 15:17,00:00:19,00,00,01,ATT unable to detect tray at Gripper 009,01,045,09/21/15 15:15,00:01:32,00,01,00,Aux tray is hanging on guides or stuck in gripper. 010,01,045,09/21/15 15:15,00:00:17,00,01,00,Aux tray is hanging on guides or stuck in gripper. 011,04,030,09/18/15 19:28,00:00:55,01,02,00,Missing sort device(s) on sort boat. B1 012,05,029,09/18/15 19:24,00:01:39,06,06,01,TS Picker missing parts:Ck #1 A1 013,05,016,09/18/15 19:21,00:01:12,00,01,00,Picker detects parts stuck in nests:Ck #1 A1 014,05,016,09/18/15 19:20,00:00:23,00,01,00,Picker detects parts stuck in nests:Ck #1 A1 015,05,016,09/18/15 19:17,00:01:07,02,03,00,Picker detects parts stuck in nests:Ck #1 A1 016,05,016,09/18/15 19:15,00:00:17,00,01,00,Picker detects parts stuck in nests:Ck #1 A1 017,05,029,09/18/15 01:52,00:00:18,00,01,00,TS Picker missing parts:Ck #1 A1 018,05,029,09/17/15 17:09,00:00:05,00,01,00,TS Picker missing parts:Ck #1 A1 019,05,029,09/17/15 17:05,00:00:06,00,01,00,TS Picker missing parts:Ck #1 A1 020,05,029,09/17/15 16:35,00:00:07,00,01,00,TS Picker missing parts:Ck #1 A1 021,05,029,09/17/15 15:37,00:00:08,00,01,00,TS Picker missing parts:Ck #1 A1 022,02,030,09/17/15 15:22,00:00:56,01,01,01,ATT unable to detect tray at Gripper 023,05,029,09/17/15 12:17,02:29:47,01,02,00,TS Picker missing parts:Ck #1 A1 024,02,016,09/17/15 12:25,00:02:15,02,03,00,ATT unable to open the Gripper 025,05,029,09/17/15 12:11,00:00:24,00,01,00,TS Picker missing parts:Ck #1 A1 026,05,029,09/17/15 09:50,00:00:06,00,01,00,TS Picker missing parts:Ck #1 A1 027,05,029,09/17/15 09:49,00:00:10,00,01,00,TS Picker missing parts:Ck #1 A1 028,05,015,09/17/15 09:48,00:00:04,00,01,00,Picker can't detect all parts:Ck #1 A1 029,05,015,09/17/15 09:47,00:00:05,00,01,00,Picker can't detect all parts:Ck #1 A1 

I wrote a LINQ request for it, which counts the total time that is added up from the field (Time Jammed) for errors (Jam ID position), but the hitch is that for nodes of all 6 of them (LM position), the errors with the same number are encountered. How to group so that it gives information node number error number total error time ???? Here is my LINQ request

 var error = (from line in readText let a = line.Split(',') where a.Length >= 5 && Regex.IsMatch(a[4], @"\d{2}:\d{2}:\d{2}") let Num = a[2] let timeAttr = a[4].Split(':') let timeUsage = TimeSpan.FromHours(int.Parse(timeAttr[0])) + TimeSpan.FromMinutes(int.Parse(timeAttr[1])) + TimeSpan.FromSeconds(int.Parse(timeAttr[2])) where timeUsage <= TimeSpan.FromHours(2) select new { Num, timeUsage } into Uzel group Uzel by Uzel.Num into g select new { Num = g.Key, TotalTime = new TimeSpan(g.Sum(arg => arg.timeUsage.Ticks)), AverageTime = new TimeSpan((long)g.Average(arg => arg.timeUsage.Ticks)) }); 

It is necessary that the data be displayed in this form (in general, what is found on the node and the time for them is only on this node and so on for 2 3, etc. node)

 На узле 01 ошибка 001 время 00:0:00 ошибка 002 время 00:02:00 ошибка 003 время 00:40:00 ................... На узле 02 ошибка 021 время 00:03:00 ошибка 003 время 00:40:00 
  • 3
    Well, at least one normal question on this topic ... - Qwertiy
  • and if you make two groupings, the first by node number, the second by error number? - Bald
  • @Creater would not be easier once to register and ask all your questions than to produce a bunch of the same type of questions from different accounts? - ApInvent
  • and I’ll write here, if you still delete your question with an answer, here you are shown how to do it, this should satisfy your needs, you only need to rewrite it a little for yourself - Bald
  • If you are given an exhaustive answer, mark it as correct (a daw opposite the selected answer). - Nicolas Chabanovsky

3 answers 3

In such cases, you can group by anonymous type, like this:

 .GroupBy(e => new {e.NodeNumber, e.ErrorNumber}) 

You needlessly mixed in one request, reading data from a file and grouping it. Reading data from an external source is one task, generating a report on the data is the second. Different tasks are best solved separately, then the code will be much easier to read and maintain.

Therefore, I would advise you to do something like this:

 // сначала читаем данные: List<Error> errors = ParseErrorsFromFile(); // функция просто парсит необходимые данные из файла // теперь группируем: var groupedErrors = errors .GroupBy(e => new {e.NodeNumber, e.ErrorNumber}) // вот то что вам нужно .Select(gr => new { gr.Key.NodeNumber, gr.Key.ErrorNumber, TotalTime = gr.Sum(x => x.TimeJummed) }) .ToList(); 

The Error class might look like this:

 public class Error { public int NodeNumber { get; set; } public int ErrorNumber { get; set; } public int TimeJummed { get; set; } } 

Here is a working example.

    You can simply make such a group by :

     group Uzel by new { Uzel.Num, Uzel.StatusCode } 

    to make it like this:

     var error = (from line in readText let a = line.Split(',') where a.Length >= 5 && Regex.IsMatch(a[4], @"\d{2}:\d{2}:\d{2}") let Num = a[2] let timeAttr = a[4].Split(':') let StatusCode = a[1] let timeUsage = TimeSpan.FromHours(int.Parse(timeAttr[0])) + TimeSpan.FromMinutes(int.Parse(timeAttr[1])) + TimeSpan.FromSeconds(int.Parse(timeAttr[2])) where timeUsage <= TimeSpan.FromHours(2) select new { Num, timeUsage, StatusCode } into Uzel group Uzel by new { Uzel.Num, Uzel.StatusCode } into g select new { Num = g.Key.Num, StatusCode = g.Key.StatusCode, TotalTime = new TimeSpan(g.Sum(arg => arg.timeUsage.Ticks)), AverageTime = new TimeSpan((long)g.Average(arg => arg.timeUsage.Ticks)) } ); 

    In general, I already gave you a link to the code that does it. And if you did not register a bunch of accounts, and used one, you would have seen it all long ago.

    • one
      But why doesn't anyone use TimeSpan.Parse ? - Qwertiy
    • @Qwertiy there, in his previous questions was a link to the entire data file. In them there are those who do not worry because there are hours> 24. Something like that in general. - ApInvent
    • @ApInvent Well, agree that this question is already of higher quality, another n * uchetok and everything will be - Bald
    • @ Bald56rus =) There were already questions, also quite detailed, with an example of its code, with example data, etc. - ApInvent
    • @ Bald56rus By the way, the request that he "himself" wrote is from the previous answers =) - ApInvent

    http://ideone.com/a1gm2u

     using System; using System.Collections.Generic; using System.Linq; public class Test { private static IEnumerable<string> ReadAllLines() { for (string line; (line=Console.ReadLine()) != null; ) yield return line; } public static void Main() { var res = from line in ReadAllLines().Skip(1) select line.Split(',') into parts group parts by parts[2] into g select new { Name = g.Key, TotalTime = g.Select(x => TimeSpan.Parse(x[4])).Aggregate(new TimeSpan(), (a,b) => a+b) }; Console.WriteLine("{0}", String.Join("\n", res)); } } 
    • and I realized that he needed grouping by nodes, errors, and there was already time - Bald
    • @ Bald56rus, reread - maybe. - Qwertiy
    • @ Bald56rus, correctly understood - Creater