LINQ:添加行号列

时间:2013-02-19 15:00:23

标签: c# .net linq

如何修改下面的查询以包含行号列(即:基于一个结果的索引)?

var myResult = from currRow in someTable
               where currRow.someCategory == someCategoryValue
               orderby currRow.createdDate descending
               select currRow;

EDIT1:我正在寻找{idx, col1, col2...col-n}而不是{idx, row}的结果。

EDIT2:行号应对应于结果行而不是表行。

EDIT3:我DataBind这些结果为GridView。我的目标是在GridView添加行号列。也许一种不同的方法会更好。

9 个答案:

答案 0 :(得分:30)

使用方法 - 语法,其中Enumerable.Select与索引重载:

var myResult = someTable.Select((r, i) => new { Row = r, Index = i })
    .Where(x => x.Row.someCategory == someCategoryValue)
    .OrderByDescending(x => x.Row.createdDate);

请注意,此方法假定您需要表中行的原始索引而不是筛选结果,因为我在使用Where进行筛选之前选择了索引。

  

编辑:我正在寻找{idx,col1,col2 ... col-n}的结果   {idx,row}。行号应该对应于结果行   表格行。

然后选择包含所需列的匿名类型:

var myResult = someTable.Where(r => r.someCategory == someCategoryValue)
        .OrderByDescending(r => r.createdDate)
        .Select((r, i) => new { idx = i, col1 = r.col1, col2 = r.col2, ...col-n = r.ColN });

答案 1 :(得分:6)

使用此Select方法:

  

通过合并元素的索引,将序列的每个元素投影到新的表单中。

示例:

var myResult = someTable.Where(currRow => currRow.someCategory == someCategoryValue)
                        .OrderByDescending(currRow => currRow.createdDate)
                        .Select((currRow, index) => new {Row = currRow, Index = index + 1});

回复您的修改:

如果您想要DataTable作为结果,只需使用DataView即可以非Linq方式使用,然后再添加一列。

someTable.DefaultView.RowFilter = String.Format("someCategory = '{0}'", someCategoryValue);
someTable.DefaultView.Sort = "createdDate";
var resultTable = someTable.DefaultView.ToTable();
resultTable.Columns.Add("Number", typeof(int));
int i = 0;
foreach (DataRow row in resultTable.Rows)
    row["Number"] = ++i;

答案 2 :(得分:3)

只是为了好玩,这里有Select的替代方案,有两个参数:

var resultsWithIndexes = myResult.Zip(Enumerable.Range(1, int.MaxValue - 1),
                                      (o, i) => new { Index = i, Result = o });

答案 3 :(得分:2)

怎么样?

int i;
var myResult = from currRow in someTable
           where currRow.someCategory == someCategoryValue
           orderby currRow.createdDate descending
           select new {Record = i++, currRow};

答案 4 :(得分:2)

根据你的编辑1. 不,你不能 Linq按原样返回表格。您可以构建每个列,但是会丢失映射实体的功能。

以前曾多次询问过这个问题:How do you add an index field to Linq results

答案 5 :(得分:1)

如果想要保持列的平面列表(即OP的编辑2)并且还想要一个适用于任何IEnumerable的通用解决方案而不要求您列出预期列的集合,则没有直接的方法。 / p>

然而,有一种迂回的方式可以解决它,即使用here中的ToDataTable()方法将查询结果转储到DataTable中,然后将RowNumber列添加到该表中。

var table = query.ToList().ToDataTable();
table.Columns.Add("RowNum", typeof(int));
int i = 0;
foreach (DataRow row in table.Rows)
    row["RowNum"] = ++i;

这可能会导致大型数据集的性能问题,但它也不会非常缓慢。在我的机器上,一个约6500行的数据集需要33ms来处理。

如果您的原始查询返回了匿名类型,那么该类型定义将在转换中丢失,因此当您调用table.AsEnumerable()时,您将失去对生成的IEnumerable的列名称的静态类型。换句话说,不是能够编写类似table.AsEnumerable()。First()。RowNum而是必须编写table.AsEnumerable()。First()[" RowNum"]

但是,如果您不关心性能并且真的想要静态键入,那么您可以使用JSON.NET将DataTable转换为json字符串,然后返回基于匿名类型的列表。原始查询结果。此方法需要占位符RowNum字段存在于原始查询结果中。

var query  = (from currRow in someTable
            where currRow.someCategory == someCategoryValue
            orderby currRow.createdDate descending
            select new { currRow.someCategory, currRow.createdDate, RowNum = -1 }).ToList();
var table = query.ToDataTable();
//Placeholder RowNum column has to already exist in query results
//So not adding a new column, but merely populating it
int i = 0;
foreach (DataRow row in table.Rows)
    row["RowNum"] = ++i;
string json = JsonConvert.SerializeObject(table);
var staticallyTypedList = JsonConvert.DeserializeAnonymousType(json, query);
Console.WriteLine(staticallyTypedList.First().RowNum);

这增加了我的6500项目数据集的处理时间约120毫秒。

这很疯狂,但确实有效。

答案 6 :(得分:0)

我知道我迟到了,但我想展示一下对我有用的东西。

我有一个对象列表,对象上有一个整数属性,用于"行号" ...或者在这种情况下,"序列号"。这就是我为填充该字段所做的工作:

myListOfObjects = myListOfObjects.Select((o, i) => { o.SequenceNumber = i; return o; }).ToList();

我很惊讶地发现这很有用。

答案 7 :(得分:0)

这对我来说很有帮助-Excel工作表提取。匿名类型

var UploadItemList = ItemMaster.Worksheet().AsEnumerable().Select((x, index) => new
{
    Code = x["Code"].Value == null ? "" : x["Code"].Value.ToString().Trim(),
    Description = x["Description"].Value == null ? "" : x["Description"].Value.ToString().Trim(),
    Unit = x["Unit"].Value == null ? "" : x["Unit"].Value.ToString().Trim(),
    Quantity = x["Quantity"].Value == null ? "" : x["Quantity"].Value.ToString().Trim(),
    Rate = x["Rate"].Value == null ? "" : x["Rate"].Value.ToString().Trim(),
    Amount = x["Amount"].Value == null ? "" : x["Amount"].Value.ToString().Trim(),
    RowNumber = index+1
}).ToList();

答案 8 :(得分:0)

int Lc = 1;

var Lst = LstItemGrid.GroupBy(item => item.CategoryName)
    .Select(group => new { CategoryName = group.Key, Items = group.ToList() ,RowIndex= Lc++ })
    .ToList();