Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
633 views
in Technique[技术] by (71.8m points)

c# - Row_number over (Partition by xxx) in Linq?

I have a DataTable which has this structure and data:

id |   inst   |   name
------------------------
 1 |  guitar  |  john
 2 |  guitar  |  george
 3 |  guitar  |  paul
 4 |  drums   |  ringo
 5 |  drums   |  pete

I can retrieve the records like this:

IEnumerable <Beatle>...

class Beatle
{
  int id;
  string inst;
  string name;
}

I'd like to get the internal order of those who play the different instruments. In MSSQL I'd use

SELECT 
    *
    ,Row_Number() OVER (PARTITION BY inst ORDER BY id) AS rn
FROM Beatles

This query returns

id |   inst   |   name  | rn
-----------------------------
 1 |  guitar  |  john   | 1
 2 |  guitar  |  george | 2
 3 |  guitar  |  paul   | 3
 4 |  drums   |  ringo  | 1
 5 |  drums   |  pete   | 2

How can I do that in Linq ?

Edit.(after accepted answer)

Full working code :

var beatles = (new[] { new { id=1 , inst = "guitar" , name="john" },
    new { id=2 , inst = "guitar" , name="george" },
    new { id=3 , inst = "guitar" , name="paul" },
    new { id=4 , inst = "drums" , name="ringo" },
    new { id=5 , inst = "drums" , name="pete" }
});

var o = beatles.OrderBy(x => x.id).GroupBy(x => x.inst)
               .Select(g => new { g, count = g.Count() })
               .SelectMany(t => t.g.Select(b => b)
                                   .Zip(Enumerable.Range(1, t.count), (j, i) => new { j.inst, j.name, rn = i }));

foreach (var i in o)
{
    Console.WriteLine("{0} {1} {2}", i.inst, i.name, i.rn);
}
question from:https://stackoverflow.com/questions/9980568/row-number-over-partition-by-xxx-in-linq

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

B"H

I know this is old. But why isn't the solution simply?

var o = beatles.GroupBy(x => x.inst)
               .SelectMany(g =>
                   g.Select((j, i) => new { j.inst, j.name, rn = i + 1 })
               );

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...