将List.foreach替换为LINQ

时间:2014-12-30 08:09:58

标签: c# .net linq

我是LINQ的新手,并用它做了一些实验。

很抱歉,如果它重复,但我似乎无法找到适当的指南(对我而言)

我想替换此代码:

DataTable table
List<string> header = new List<string>();
table.Columns.Cast<DataColumn>().ToList().ForEach(col => header.Add(col.ColumnName));

使用LINQ之类的东西:

var LINQheader = from mycol in table.Columns select mycol.ColumnName;
LINQheader.tolist();

但它甚至没有编译。 我想要的不是一个单行解决方案,而是想要一些逻辑来理解如何用更复杂的环境构建它(比如用一些逻辑选择XML中的许多节点)

6 个答案:

答案 0 :(得分:3)

您可以使用Enumerable.Aggregate()

var header = table.Columns.Cast<DataColumn>().Aggregate(new List<string>(), (list, col) => { list.Add(col.ColumnName); return list; });

通常,Linq允许从数据源检索和转换数据序列。你想在这个问题上做的是迭代一个序列并返回一个立即的结果。这不是Linq的主要关注点,但有些方法可以执行tasks like this,包括Aggregate()Average()Count()Max()等等。

答案 1 :(得分:3)

这是原始代码

table.Columns.Cast<DataColumn>().ToList().ForEach(col => header.Add(col.ColumnName));

为什么使用Cast? 因为它允许您将DataColumnCollection项视为DataColumn而不是对象。

为什么使用ToList? 因为它会将您的IEnumerable转换为List并允许您调用ForEach,因为此函数是List类中存在的特殊方法。

为什么使用ForEach? 因为它允许你为列表中的每个元素做你想要的事情(在你的情况下,它将每列的列名添加到另一个列表(header))。

简化版:

现在假设您要将列名称添加到header,以#34; Student&#34; 你可以写这样的东西

DataTable table = new DataTable();
List<string> header = new List<string>();

foreach (DataColumn col in table.Columns)
{
    if (col.ColumnName.StartsWith("Id")) // you can remove this line if you want to add all of them
       header.Add(col.ColumnName);
}

您也可以使用此

table.Columns.Cast<DataColumn>()
    .ToList()
    .ForEach(col =>
    {
        if (col.ColumnName.StartsWith("Id"))
            header.Add(col.ColumnName)
    });

var headers = table.Columns.Cast<DataColumn>()
        .Where(col => col.ColumnName.StartsWith("Id"))
        .Select(col => col.ColumnName);

header.AddRange(headers);

答案 2 :(得分:2)

var LINQheader = from mycol in table.column select mycol.ColumnName;
LINQheader.tolist();

这不会编译,因为DataTable中没有column这样的属性,只有Columns,你必须使用.Cast()方法,因为它们不是实现正确的界面(参见@Uriil的回答)。

试试这个:

var LINQheader = from mycol in table.Columns.Cast<DataColumn>()
                  select mycol.ColumnName;
LINQheader.tolist();

如果你想在扩展方法中使用它,你可以这样做:

public static IEnumerable<string> GetHeaderColumns (this DataTable dataTable) 
{
    if (dataTable == null || !dataTable.Columns.Any())
    {
        yield break;
    }
    foreach (var col in dataTable.Columns.Cast<DataColumn>())
    {
        yield return col.ColumnName;
    }
}

答案 3 :(得分:2)

    static void Main(string[] args)
    {
        DataTable tbl = new DataTable();
        tbl.Columns.Add("A");
        tbl.Columns.Add("B");

        var p = from DataColumn col in tbl.Columns select col.ColumnName;

        foreach(string a in p)
        {
            Console.WriteLine(a);
        }
    }

这里有一些代码示例。如果您想成为List<string>,请使用ToList()

修改

就像@Grundy所说你缺少指定col的类型,即DataColumn。

List<string> columnList = (from DataColumn mycol in table.Columns select mycol.ColumnName).ToList();

这将是你的一行。

答案 4 :(得分:1)

为什么不简单选择

DataTable table;
IEnumerable<string> header = from mycol in table.Columns.Cast<DataColumn>()
                             select mycol.ColumnName;

答案 5 :(得分:1)

您遇到了一些问题,需要解决方法:

  1. ForEach是List specifict方法,因此无法将其转换为LINQ
  2. LINQ用于数据选择,聚合,但不用于数据 修改
  3. table.Columns,返回DataColumnCollection,但不返回IEnumerable<T> 实现var LINQheader = from mycol in table.Columns.Cast<DataColumn>() select name.ColumnName; ,所以无论如何你都必须施展它:

    {{1}}