63

Lets say I have an array like this:

string [] Filelist = ...

I want to create an Linq result where each entry has it's position in the array like this:

var list = from f in Filelist
    select new { Index = (something), Filename = f};

Index to be 0 for the 1st item, 1 for the 2nd, etc.

What should I use for the expression Index= ?

Keltex
  • 26,220
  • 11
  • 79
  • 111

3 Answers3

140

Don't use a query expression. Use the overload of Select which passes you an index:

var list = FileList.Select((file, index) => new { Index=index, Filename=file });
patridge
  • 26,385
  • 18
  • 89
  • 135
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • How do you do this in sql syntax? – toddmo Apr 30 '17 at 20:15
  • @toddmo: By "in sql syntax" do you mean "using LINQ query expressions"? If so, you can't. If you mean "in SQL itself" then I don't know - I suspect there are non-portable ways of doing it. – Jon Skeet May 01 '17 at 06:07
  • 2
    I figured it out, thanks. I meant this: `(from GHCOPPADriverType driver in policy.Drivers from GHCOPPADriverHistoryType driverHistory in driver.Rating_DrivingHistory select (driver: driver, history: driverHistory)) .Select((t,i) => new DriverHistoryModel(t.history) { DriverId = t.driver.Id, Sequence = i + 1 });`. So I did have to get out of query expressions to use the `Select` overload. – toddmo May 01 '17 at 19:56
  • @JonSkeet is the king. thanks. – James Harcourt Jun 12 '23 at 14:50
2
string[] values = { "a", "b", "c" };
int i = 0;
var t = (from v in values
select new { Index = i++, Value = v}).ToList();
GeekyMonkey
  • 12,478
  • 6
  • 33
  • 39
  • 4
    Why go to all that trouble instead of using the version that's provided by the framework? – Jon Skeet Nov 06 '08 at 15:37
  • 1
    Why not!? It works. You have full control this way. I probably wouldn't do this myself, but that's the question that was asked. – GeekyMonkey Nov 09 '08 at 00:18
  • 2
    But if you run/invoke/trigger the query twice you'll get differnt IDs - I wouldnt mind if there was a ToArray on the end to hilight this... – Ruben Bartelink Jan 21 '09 at 10:00
  • 8
    Plus, with the new paralleling that can be applied to linq, you could have them out of order and even using the same numbers. Ouch! – Matt DeKrey Jun 09 '10 at 20:55
  • Valid points. I was just trying to give a simple answer to a simple question. The above code should be wrapped in a neat little function (or at least curly braces) that only allows the query to run once, and then "i" would go out of scope, and it should not be used with parallel link obviously. – GeekyMonkey Jun 16 '10 at 11:13
  • How's your code simpler than the overload of select that provides the index? – Rune FS Sep 28 '11 at 07:39
  • 1
    It uses the alternate syntax, not requiring a lambda. As I said, I wouldn't recommend this method, just providing an alternative answer. Food for thought. – GeekyMonkey Oct 07 '11 at 12:27
  • 1
    Old topic, I know.. But I do think that it is important to note that while it is true that if the query is executed multiple times it will return different results, it is NOT true that simply appending ToArray after ToList will result in that behavior (try it). It just shows that if you are going to use linq you need a handle on when your queries are executing and what the implications are. I came across someone who was trying to do an unsupported grouping, it didn't work until he added ToList() on the base queryable, he got the result he wanted from the database, until there was more data. – vbigham Jan 31 '14 at 05:27
1

You cannot get an index using pure LINQ query expressions (those with from.. where.. select.. clauses).

However, this doesn't mean you have to completely give up on this LINQ query style.

You just have to get out of the LINQ query expression and use a .Select(item, index) method overload.

var newestExistingFilesWithIndexes = 
    (from f in Filelist
     // we love LINQ query expressions
     where f.Exists
     // and we use it anywhere possible
     orderby f.LastModified descending
     select f)
     // but sometimes we have to get out and use LINQ extension methods
    .Select((f, index) => new { Index = index, Filename = f.Fullname});

or suppose, you need to filter a list based on item index ...

var newestExistingFilesOnlyEvenIndexes = 
     // use the Select method overload to get the index
    (from f in Filelist.Select((file, index) => new { file, index })
     // only take item with an even index
     where f.index % 2 == 0
     where f.file.Exists
     orderby f.file.LastModified descending
     select f.file);
Artemious
  • 1,980
  • 1
  • 20
  • 31