31

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

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. 也许另一种方法会更好。

4

9 回答 9

42

使用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 });
于 2013-02-19T15:03:42.403 回答
6

使用此Select方法:

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

例子:

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

回应您的编辑:

如果您想要 a作为结果,您可以通过简单地使用 a并在之后添加一个附加列DataTable来采用非 Linq 方式。DataView

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;
于 2013-02-19T15:02:28.160 回答
3

关于什么?

int i;
var myResult = from currRow in someTable
           where currRow.someCategory == someCategoryValue
           orderby currRow.createdDate descending
           select new {Record = i++, currRow};
于 2013-02-19T15:04:15.417 回答
3

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

var resultsWithIndexes = myResult.Zip(Enumerable.Range(1, int.MaxValue - 1),
                                      (o, i) => new { Index = i, Result = o });
于 2013-02-19T15:07:13.493 回答
2

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

之前已经多次问过这个问题: 如何在 Linq 结果中添加索引字段

于 2013-02-19T15:24:56.357 回答
1

如果想要保持列的平面列表(即 OP 的 Edit2)并且还想要一个通用的解决方案,该解决方案可以与任何 IEnumerable 一起使用,而无需您列出预期列的集合,则没有直接的方法。

但是,有一种迂回的方法可以解决这个问题,即使用 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 行的数据集需要 33 毫秒来处理。

如果您的原始查询返回一个匿名类型,那么该类型定义将在转换中丢失,因此当您调用 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 毫秒的处理时间。

这很疯狂,但它有效。

于 2016-07-08T00:07:53.033 回答
0

我知道我迟到了,但我想展示什么对我有用。

我有一个对象列表,该对象上有一个整数属性,用于“行号”......或者在本例中为“序列号”。这是我为填充该字段所做的:

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

看到这行得通,我很惊讶。

于 2016-12-22T20:09:11.253 回答
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();
于 2019-08-01T13:12:48.823 回答
0
int Lc = 1;

var Lst = LstItemGrid.GroupBy(item => item.CategoryName)
    .Select(group => new { CategoryName = group.Key, Items = group.ToList() ,RowIndex= Lc++ })
    .ToList();
于 2020-04-12T06:29:06.887 回答