Getting the first member of a Dictionary and then the rest of it

My class object has a dictionary in it like this:

class MyClass
{
  Dictionary<string, string> Things {get; set;}
}

now I want to get the first thing to do something special on it and then if it had more members take the rest of them and do some other thing on the rest of them

I had seen some syntax for Select statement that we could pass an "index" to Select, I was trying to figure it out but no luck. How would you do that?

All I wrote was something like this:

var temp = myClassObject.Things.Select((t,i) => t.Vale);

I think I can write it in a lengthier way by using .First and Skip(1).

Upvotes: 2

Views: 78

Answers (4)

Tim Schmelter
Tim Schmelter

Reputation: 460048

Dictionaries should not be used if you have to rely on a specific order. They are used to lookup a value by a key fast. However, as long as you don't remove entries the current implementation preserves the insertion order.

So you can treat it like a collection and use Take(or First if you want to stop the query) and Skip:

var firstThing   = Things.Take(1);  // or First()
var restOfThings = Things.Skip(1);

Upvotes: 3

p.s.w.g
p.s.w.g

Reputation: 148980

As the other answers have stated, items in dictionaries not have a defined order, and you shouldn't rely on a dictionary to return the items in the same order in which they were added. If this is really something you need, I'd strongly recommend you rethink your choice of data structure.

However, since you said you didn't want to use First or Skip, you could use the raw IEnumerator instead:

using (var enumerator = myClassObject.Things.GetEnumerator())
{
    if (enumerator.MoveNext())
    {
        var firstPair = enumerator.Current;
        // Handle first pair

        while (enumerator.MoveNext())
        {
            var pair = enumerator.Current;
            // Handle subsequent pairs
        }
    }
}

To be honest, I probably wouldn't do this in my own code; I'm just offering an alternative.

Upvotes: 0

D Stanley
D Stanley

Reputation: 152501

As I said in my comment, Dictionaries are not ordered, so getting the "First" item may give you inconsistent results.

That said, it does implement IEnumerable<KeyValuePair>, so you could do:

string firstItem = myClassObject.Things.First().Value;
IEnumerable<string> theRest = myClassObject.Things.Skip(1).Select(kvp => kvp.Value);

If you want to keep the items in the order in which they're added then a List<string> is more appropriate (or a List<Tuple<string, string>> if you want to keep some string value associated with the line). The main difference is that getting items will be slower (how much slower depends on the amount of data)

Upvotes: 2

Travis J
Travis J

Reputation: 82267

I would suggest introducing a tuple to this

Dictionary<string, Tuple<string,int>> Things {get; set;}

And then when building your data, as opposed to just using

Things["Hello"] = "World";

You would use a counter which started at 0

Things["Hello"] = new Tuple<string,int>("World",counter++);

And this would allow you to later look at the first line

var first = Things.OrderBy(k => k.Value.Item2).First();

and

var rest = Things.OrderBy(k => k.Value.Item2).Skip(1);

Upvotes: 2

Related Questions