This is a neat little trick that I came across when looking for a way to arbitrarily assign a unique index to each element in a collection. Imagine a scenario where you have a collection of a class such as the following:
class TestIndex { public string Title { get; set; } public int Amount { get; set; } public int Index { get;set; } public override string ToString() { return string.Format("{0}: {1}, {2}", Index, Title, Amount); } }
Here’s the code to populate it:
List<TestIndex> l = new List<TestIndex>() { new TestIndex() { Title="test1", Amount=20 }, new TestIndex() { Title="test2", Amount=30 }, new TestIndex() { Title="test3", Amount=5 }, new TestIndex() { Title="test4", Amount=30 } };
I’ve overriden ToString so that we can see what’s in it:
foreach (var t in l) { Console.WriteLine(t.ToString()); }
A you can see, we have a field called Index, but it contains nothing (well, 0). However, it can be populated in a single line:
var newList = l.Select((el, idx) => { el.Index = idx; return el; });
The Select statement has an override that will tell you the index of that element based on the order; for example:
var newList = l.OrderBy(a => a.Amount).Select((el, idx) => { el.Index = idx; return el; });
Complete Code Listing
class Program { static void Main(string[] args) { List<TestIndex> l = new List<TestIndex>() { new TestIndex() { Title="test1", Amount=20 }, new TestIndex() { Title="test2", Amount=30 }, new TestIndex() { Title="test3", Amount=5 }, new TestIndex() { Title="test4", Amount=30 } }; foreach (var t in l) { Console.WriteLine(t.ToString()); } Console.WriteLine(" - - - "); var newList = l.Select((el, idx) => { el.Index = idx; return el; }); foreach (var t in newList) { Console.WriteLine(t.ToString()); } Console.ReadLine(); } } class TestIndex { public string Title { get; set; } public int Amount { get; set; } public int Index { get;set; } public override string ToString() { return string.Format("{0}: {1}, {2}", Index, Title, Amount); } }