-1

I have a variable called data that is defined as:

Dictionary<string[], Dictionary<string, float>> data

As you can see, the key is a string array and the value is another inner dictionary. Each key can have items like:

{"xxx", "ccc", "wpr", "qpr"}
{"xxx", "abd", "xyz", "qpr"}
{"yyy", "ddd", "kgo", "abc"}

How can I use LINQ to get the distinct first items of this key? For example, in my example above, I should get xxx and yyy as a result. Two of these keys have xxx and one has yyy as their first items.

The array of strings in the key of this Dictionary is used as a row identifier. The data that this Dictionary contains is data that is exported to Excel. I inherited this application so I cannot redefine this variable. So the key is used to identify and do a grouping of totals in Excel. This is why the original developer did it this way.

The string keys will always have the same length.

Ray
  • 4,679
  • 10
  • 46
  • 92
  • 2
    A `String[]` as key, why? That doesn't work without a custom `IEqualityComparer(string[])` – Tim Schmelter Apr 29 '15 at 14:58
  • Are the arrays always the same length? If they are, I wouldn't be using an array. – Charles Mager Apr 29 '15 at 15:00
  • Can you explain how "find distinct of first elements of group of arrays" is related to dictionary? I don't yet to see that connection and concerned about quality of the question because of that. – Alexei Levenkov Apr 29 '15 at 15:06
  • Side note: if you happen to use such dictionary make sure to have proper custom comparer similar to one covered in http://stackoverflow.com/questions/14663168/an-integer-array-as-a-key-for-dictionary – Alexei Levenkov Apr 29 '15 at 15:09
  • Although you marked my answer as being correct, you should read and understand the other answers. Using a string array as a key is probably a very bad idea. By default, it doesn't use the values of the array as the key but the reference, which is counter intuitive and easy for someone not so well versed in how it works to make all sorts of false assumptions. – Robert McKee Apr 29 '15 at 15:18

2 Answers2

4

Something like...

var result=data.Keys.Select(k=>k[0]).Distinct();
Robert McKee
  • 21,305
  • 1
  • 43
  • 57
  • Excellent, this worked for me. Learned something new on how LINQ works with Dictionaries. Thanks! – Ray Apr 29 '15 at 15:06
0

It doesn't work as expected to use a String[] as key in a dictionary since that type doesn't override Equals + GetHashCode. You need a custom IEqualityComparer(string[]) for the dictionary constructor if you don't want to compare only references.

Apart from that, try this:

IEnumerable<string> firstColumnDistinct = data.Keys
   .Select(arr => arr.FirstOrDefault())
   .Distinct();

FirstOrDefault handles also the case that an array is empty.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • 1
    Correct. Assuming the `string[]` keys will always have the same length, one can implement the curstom `IEqualityComparer` you mention quite simply: `class MyStringArrayEqualComp : EqualityComparer { public override bool Equals(string[] x, string[] y) { return System.Collections.StructuralComparisons.StructuralEqualityComparer.Equals(x, y); } public override int GetHashCode(string[] obj) { return System.Collections.StructuralComparisons.StructuralEqualityComparer.GetHashCode(obj); } }` – Jeppe Stig Nielsen Apr 29 '15 at 15:08
  • Note that the empty array will be in the same "group" as the non-empty arrays whose 0th entry is the `null` reference. – Jeppe Stig Nielsen Apr 29 '15 at 15:13
  • @JeppeStigNielsen: thanks for mentioning `StructuralEqualityComparer`. Yes, it's the same, depends on if that is preferred or an exception at `k[0]` as in the accepted. – Tim Schmelter Apr 29 '15 at 15:14