【问题标题】:LINQ: Add RowNumber ColumnLINQ:添加行号列
【发布时间】:2013-02-19 15:00:23
【问题描述】:

如何修改下面的查询以包含行号列(即:基于 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 中添加一个行号列。也许另一种方法会更好。

【问题讨论】:

标签: c# .net linq


【解决方案1】:

使用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,行}。行号应该对应于结果行而不是 表格行。

然后选择你需要的所有列的匿名类型:

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 });

【讨论】:

  • 我正在寻找一种解绑 currRow 的解决方案。 (见主帖编辑)
  • @Steven:编辑了我的答案。您可以使用匿名类型。
  • @Steven:您可以将此结果数据绑定到 GridView。你遇到了什么问题?
  • 问题已解决。我找到了一种以两种不同方式创建行号列的方法(1)通过 LINQ 添加索引或(2)添加TemplateFieldItemTemplateContainer.DataItemIndex + 1。 ...我相信我的实际问题是我对 .NET 的随学随用的知识参差不齐。我可能应该回去通过一些结构化的培训学习 .NET。
  • 我是 Linq 查询的新手,所以在这里为了检索所有列,包括新添加的行号。需要进行哪些修改(如果有 10 列或更多列指定每个将是硬)
【解决方案2】:

使用这个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;

【讨论】:

  • 假定 OP 想要应用过滤器后的行索引,而不是表中行的索引。
【解决方案3】:

怎么样?

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

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

    • @Steven:你打算如何使用这些新结果?你有对应结构的类型吗?
    • 我将DataBind结果到一个GridView。我正在尝试向 GridView 添加行号列。
    【解决方案5】:

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

    这已经被问过多次了:How do you add an index field to Linq results

    【讨论】:

      【解决方案6】:

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

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

      这很疯狂,但它确实有效。

      【讨论】:

        【解决方案7】:

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

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

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

        我很惊讶这能奏效。

        【讨论】:

          【解决方案8】:

          在我的情况下,这对我有所帮助 - 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();
          

          【讨论】:

            【解决方案9】:
            int Lc = 1;
            
            var Lst = LstItemGrid.GroupBy(item => item.CategoryName)
                .Select(group => new { CategoryName = group.Key, Items = group.ToList() ,RowIndex= Lc++ })
                .ToList();
            

            【讨论】:

            • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常质量更高,更容易吸引投票。
            猜你喜欢
            • 2011-05-19
            • 1970-01-01
            • 2020-04-03
            • 2018-07-30
            • 1970-01-01
            • 1970-01-01
            • 2023-03-14
            • 2011-10-15
            • 1970-01-01
            相关资源
            最近更新 更多