SoftCircuits / OrderedDictionary

.NET library that implements an ordered dictionary.
MIT License
11 stars 2 forks source link

Unable to enumerate the dictionary (KeyValuePair<k, v>) in order it was populated #1

Closed timmi4sa closed 2 years ago

timmi4sa commented 2 years ago

I wouldn't write this if I didn't see a great future/use for this library, thank you for creating a Nuget!

Pardon my ignorance or lack of understanding, but I am unable to get the dictionary Keys in the order the key/value pair has been added/inserted into the dictionary. I can see how to retrieve the Values in correct order, but not the Key with Value.

We are trying to use this OrderedDictionary as a class property during JSON de-serialization and need deserialized properties (along with their respective keys).

Trying to do an enumeration as follows raises the "Not Implemented" exception, we, of course can inherit from SoftCircuits.OrderedDictionary class and override it but it would be nice to be able to recommend this Nuget to other developers without the need to do this extra work (which would definitely poor cold water on the recommendation):

foreach (KeyValuePair<k, v> orderedKeyWithValue in myOrderedDictionary)
{
    // use orderedKeyWithValue.Key -and- orderedKeyWithValue.Value
}

As an alternative we would be glad to use a new "OrderedKeys" property if the enumeration above is, for whatever reason, to be avoided.

Please advise.

Tim

SoftCircuits commented 2 years ago

Yes, the keys are not ordered. They are used only to locate collection items by key.

The way I would approach this, I would store a class type for the values that includes the key. You could then retrieve the values in order and would have the key.

I supposed the class could be implemented to store the keys in order. This would allow you to retrieve the ordered keys. But it would require an additional step to retrieve the values in order. So I would need some good example use cases to change this.

timmi4sa commented 2 years ago

@SoftCircuits Perhaps I am lacking a basic understanding of the purpose of this "OrderedDictionary". My understanding is that such the collection 1) should maintain the order of elements the way the elements have been added/inserted, 2) the collection should provide a lookup functionality by a key, 3) the enumeration of such collection should provide the elements in the order these have been added/inserted. The item 3 is what seems to be missing (element is a key+value pair).

You mentioned "This would allow you to retrieve the ordered keys. But it would require an additional step to retrieve the values in order. ", if the element (key+value) is stored in an ordered fashion the key would not need to be ordered on its own, but I recognize that you are the implementer and it's most likely more evident "to you" that the reality is a lot more complicated.

The usage example is round-tripping a JSON file. Step 1: reading the file into memory, Step 2) Parsing JSON into a C# object (of known structure) that includes a Dictionary<string, object> property, Step 3) The JSON file is then regenerated (with white-space/indentations removed) while preserving the order of the dictionary keys to match the original JSON file.

Example (source JSON):

{
    Parameters: {
       "Zoom": 80,
       "Opacity": 0.85,
       "Background": "#fff",
       "Job": "A2345948"
    },
   ...
}
public class DeserializedAs
{
    public OrderedDictionary<string, object> Parameters { get; set; }
    //.. more properties
}

Example (destination JSON): { Parameters: { "Zoom": 80, "Opacity": 0.85, "Background": "#fff", "Job": "A2345948" }, ... }

Note that the order of parameters is to be preserved: Zoom, Opacity, Background, Job. When using the stock Dictionary<k, v>, the order of the keys is arbitrary.

I hope I have shed more light on the perceived issue.

SoftCircuits commented 2 years ago

I uploaded an update. Version 2.1.0 allows you to access the ordered keys in one of two ways.

foreach (var key in dictionary.Keys)
{
}

And:

foreach (KeyValuePair<string, string> pair in (IEnumerable<KeyValuePair<string, string>>)dictionary)
{
}

This is one of my smaller packages but I am looking to update all of my packages. So if you see any other issues, please let me know.

timmi4sa commented 2 years ago

@SoftCircuits Jonathan I am sorry I haven't provided feedback promptly. The updates work like a charm, it helped me tremendously! Thank you for your attention to this matter!

SoftCircuits commented 1 year ago

FYI, in version 3.0.0, using foreach directly on the collection will enumerate the underlying KeyValuePair<TKey, TValue>s in the collection in the order the items were added. This more closely matches the value of Dictionary<TKey, TValue>. To enumerate the keys or values, use the Keys or Values properties.