1

I have a dictionary object

Dictionary<double, byte[]>

that has keys such as 1.0, 1.1, 1.2, 2.0, 2.1, 2.2, 2.3, 2.4, 3.0, 4.0, ...

I need to concatenate the values (byte[]) such that values with keys 1.0, 1.1, 1.2 is one byte[], values with keys 2.0, 2.1, 2.2, 2.3, 2.4 is one byte[], and so forth.

I am able to get the number of bytearrays I need to end up with but there has to be a more efficient way than how I am trying to do this.

var keys = chunkedStates.Keys;
List<int> Ids = new List<int>();
foreach(var key in keys)
            {
                var Id = Convert.ToInt32(Math.Truncate(key));
                if (!Ids.Contains(Id))
                {
                    Ids.Add(Id);
                }
            }

So Ids.Count represents the number of bytearrays I should have after the concatenation. But I am stuck as to how to proceed from here...

Any pointers are appreciated.

Manas
  • 521
  • 8
  • 26
  • 5
    `double` makes a **terrible, terrible** dictionary key, btw; keys depend on exact equality; and the one thing you rarely have with `double`: exact equality – Marc Gravell Aug 29 '14 at 07:38
  • @MarcGravell thanks for the tip. Will fix. – Manas Aug 29 '14 at 07:39
  • @MarcGravell, please tell can we use `SortedDictionary` here? Also what if you actually need something like this with `double`? – Hassan Aug 29 '14 at 07:46
  • @HassanNisar `SortedDictionary` will handle the *ordering* issue (although it has different costs); it won't handle the rest of it – Marc Gravell Aug 29 '14 at 07:47

4 Answers4

1
    Dictionary<int, byte[]> results = new Dictionary<int, byte[]>();
    foreach(var grp in data.OrderBy(pair => pair.Key)
               .GroupBy(pair => (int)pair.Key, pair => pair.Value))
    {
        byte[] result;
        if (grp.Count() == 1)
        {
            result = grp.Single();
        }
        else {
            result = new byte[grp.Sum(arr => arr.Length)];
            int offset = 0;
            foreach(byte[] arr in grp)
            {
                Buffer.BlockCopy(arr, 0, result, offset, arr.Length);
                offset += arr.Length;
            }
        }
        results.Add(grp.Key, result);
    }
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
1

You can use ToLookup:

ILookup<int, double> lookup = keys.ToLookup(d => (int)d);

If you want a List<int[]> where each entry contains all doubles for that integer:

List<double[]> bytes = lookup
            .Select(g => g.OrderBy(d => d).ToArray())
            .ToList();

But note that you should not use double as key in a dictionary since it does not repsent exact values but a dictionary needs to have exact keys, otherwise you don't find them or you get exceptions because of duplicates.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
0

referring to this: http://www.dotnetperls.com/sort-dictionary. In C#, Dictionary has no sort method. You must separately acquire the element and sort them. Something useful is here: How do you sort a dictionary by value?

Community
  • 1
  • 1
Masoud
  • 1,343
  • 8
  • 25
0

Using LINQ you could write it like this:

var Ids = (from key in chunkedStates.Keys
           select Convert.ToInt32(Math.Truncate(key))).Distinct().ToList();
toadflakz
  • 7,764
  • 1
  • 27
  • 40