Assigning an index to a collection using LINQ

January 21, 2015

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

linq1

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

linq2

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

linq3

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



Profile picture

A blog about one man's journey through code… and some pictures of the Peak District
Twitter

© Paul Michaels 2024