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);
}
}