4 Replies - 225 Views - Last Post: 13 February 2019 - 04:07 PM

#1 andrewsw   User is online

  • never lube your breaks
  • member icon

Reputation: 6798
  • View blog
  • Posts: 28,095
  • Joined: 12-December 12

iterate list with index

Posted 13 February 2019 - 05:47 AM

It is a little odd that C# does not have a native way to iterate a List<> with the index available, 0,1,2. Many languages have this facility (e.g. Python, PHP).

We could just use a foreach loop and a counter, or a for loop, but neither is too pretty.

I borrowed this extension method and modified it. I wanted to see how it would work with a Tuple rather than a separate defined struct.

    public static class ExtensionMethods
    {
        public static IEnumerable<Tuple<T, long>> Enumerate<T>(this IEnumerable<T> collection)
        {
            long counter = 0;

            foreach (var item in collection)
            {
                yield return new Tuple<T, long>(item, counter++);
            }
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            var data = new string[] { "bob", "ted", "fred" };

            foreach (var item in data.Enumerate())
            {
                Console.WriteLine($"{item.Item1} - {item.Item2}");
            }

            Console.ReadKey();
        }
    }


output:
bob - 0
ted - 1
fred - 1

I don't like the references Item1, Item2, though. Unfortunately, there is no way to change them in C#6, discussed here. We can in C#7, which is nice.

Do you have comments on this or a preferred approach?
Do you think such a feature should be available directly? After all, the indexing is an integral (excuse the pun) part/feature of List<T>.

Is This A Good Question/Topic? 0
  • +

Replies To: iterate list with index

#2 andrewsw   User is online

  • never lube your breaks
  • member icon

Reputation: 6798
  • View blog
  • Posts: 28,095
  • Joined: 12-December 12

Re: iterate list with index

Posted 13 February 2019 - 07:11 AM

I was thinking about maybe using yield with an out parameter to collect the indexes, but out or ref parameters cannot be used with iterators, groan.

So maybe an anonymous type collection:

        public static IEnumerable<object> Enumerate2<T>(this IEnumerable<T> collection)
        {
            long counter = 0;

            foreach (var item in collection)
            {
                //yield return new Tuple<T, long>(item, counter++);
                yield return new { index = counter++, item = item };
            }
        }

but we cannot reference the values directly by name, item.index, as the return is just an 'object'. We can use dynamic type, though, to achieve this:
            foreach (dynamic item in data.Enumerate2())
            {
                Console.WriteLine($"{item.index} - {item.item}");
            }

but if I'm going to use dynamic I might as well revert to the original version with a struct :rolleyes:
Was This Post Helpful? 0
  • +
  • -

#3 modi123_1   User is online

  • Suitor #2
  • member icon



Reputation: 15108
  • View blog
  • Posts: 60,430
  • Joined: 12-June 08

Re: iterate list with index

Posted 13 February 2019 - 08:10 AM

Maybe a tangentially interesting read.

C# 8: slicing with Indexes and Ranges
https://www.codejour...indexes-ranges/
Was This Post Helpful? 1
  • +
  • -

#4 andrewsw   User is online

  • never lube your breaks
  • member icon

Reputation: 6798
  • View blog
  • Posts: 28,095
  • Joined: 12-December 12

Re: iterate list with index

Posted 13 February 2019 - 08:18 AM

Thanks

:groan: I'm not in favour of this constant purloining of features and syntax from other languages (Python, Java, YourGran, etc.). There is too much noise already?!

[I know that I mentioned the possibility of my discussion feature being added to the language, but I only did so to encourage the discussion - I don't really care whether it is ever added ;) ]
Was This Post Helpful? 0
  • +
  • -

#5 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 6967
  • View blog
  • Posts: 23,676
  • Joined: 05-May 12

Re: iterate list with index

Posted 13 February 2019 - 04:07 PM

Select() seems to work for me.

var names = new string [] { "Kirk", "Picard", "Janeway" };
var nameIndexes = names.Select((name, index) => (name, index));
foreach(var (name, index) in nameIndexes)
    Console.WriteLine($"{index}: {name}");


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1