0

Let's say I've a class Telemetry as follows:

public class Telemetry
{
   public string Id { get; set; }
   public AdditionalInfo Info { get; set; }
}

Let's say I've a class: TelemetryCollection that implements : IEnumerable<IList<Telemetry>>

I need to group an instance of TelemetryCollection based on Telemetry.Id and get a mapping of Telemetry.Id and TelemetryCollection

How do I get an IDictionary<string, IEnumerable<IList<Telemetry>>> from IEnumerable<IList<Telemetry>>>

Manikanta
  • 73
  • 6
  • A Dictionary is *very* different from a list or array. You can't just cast an array of arrays to a dictionary. You'll have to *fill* a dictionary with that data, providing a key for each element. Without any code or relevant classes it's hard to post an actual question. If you have 1000 Telemetry instances, which Id are you going to use as a key? Or perhaps you want a different key? – Panagiotis Kanavos Sep 07 '21 at 09:22
  • Where does this nested list come from anyway? There may be better ways to create the results you want. For example, LINQ's `GroupBy`, `ToDictionary` and `ToLookup` can be used to group items by key – Panagiotis Kanavos Sep 07 '21 at 09:23
  • TelemetryCollection should ideally have objects of Telemetry with the same Id. But in some rare cases (e.g., when multiple tests are run simultaneously), TelemetryCollection may have objects with different Id. In that case, I want to break one TelemetryCollection into multiple TelemetryCollection objects grouped by their Ids. – Manikanta Sep 07 '21 at 09:28
  • A nested List may not be a good thing. I agree. But it's some legacy code and I don't have much options here. – Manikanta Sep 07 '21 at 09:30
  • What if the duplicate IDs are distributed across multiple nested collections? How would the dictionary value be determined in that case? – Johnathan Barclay Sep 07 '21 at 09:57
  • I'm currently doing a SelectMany on the TelemetryCollection and flattening all the objects. Then iterating over all of them and populating a dictionary. Wanted to know if there was any other better approach. – Manikanta Sep 07 '21 at 10:00
  • So should the result actually be `IDictionary>`? – Johnathan Barclay Sep 07 '21 at 10:01

1 Answers1

1

Assuming TelemetryCollection contains arrays/lists of Telemetry measurements for the same Id with possible duplicates, you can:

  1. Group the arrays using group by the first array element's Id
  2. Use ToDictionary to collect the grouped arrays into a dictionary
var dict=collection.GroupBy(t=>t[0].Id)
                   .ToDictionary(g=>g.Key,
                                 g=>g.AsEnumerable());

The following example compiles:

//Use a record to save keystrokes
public record Telemetry(string Id ,int Info );

IEnumerable<IList<Telemetry>> collection=new List<IList<Telemetry>>{
            new[]{ new Telemetry("A",1),new Telemetry("A",2)},
            new[]{ new Telemetry("B",1),new Telemetry("B",2)},
            new[]{ new Telemetry("A",3),new Telemetry("A",4)}
        };
var dict=collection.GroupBy(t=>t[0].Id)
                   .ToDictionary(g=>g.Key,g=>g.AsEnumerable());
Console.WriteLine(dict);

And prints:

System.Collections.Generic.Dictionary'2[System.String,System.Collections.Generic.IEnumerable'1[System.Collections.Generic.IList`1[ConsoleApp1.Telemetry]]]

Serializing dict to JSON produces:

{
   "A":[
          [{"Id":"A","Info":1},{"Id":"A","Info":2}], 
          [{"Id":"A","Info":3},{"Id":"A","Info":4}]
       ],
   "B":[
          [{"Id":"B","Info":1},{"Id":"B","Info":2}]
       ]
}

This won't work if there are any empty arrays in TelemetryCollection. This can be fixed if FirstOrDefault() is used to retrieve the first key and defaulting to "" if there's none :

var dict=collection.GroupBy(t=>t.FirstOrDefault()?.Id??"")
                   .ToDictionary(g=>g.Key,
                                 g=>g.AsEnumerable());
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236