Reputation: 863
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
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
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
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
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