将 List.foreach 替换为 LINQ
本文关键字:LINQ 替换 foreach List | 更新日期: 2023-09-27 18:35:42
我是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中选择具有某些逻辑的许多节点)
这里是原始代码
table.Columns.Cast<DataColumn>().ToList().ForEach(col => header.Add(col.ColumnName));
为什么使用Cast
?
因为它允许您将DataColumnCollection
项视为DataColumn
而不是对象。
为什么使用ToList
?
因为它将您的IEnumerable
转换为List
并允许您调用ForEach
因为此函数是存在于List
类中的特殊方法。
为什么使用ForEach
?
因为它允许您对列表中的每个元素执行所需的操作(在您的情况下,它将每列的列名添加到另一个列表( header
))。
简体版:
现在假设您要将列名称添加到以"学生"开头的header
你可以写这样的东西
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);
您可以使用Enumerable.Aggregate()
var header = table.Columns.Cast<DataColumn>().Aggregate(new List<string>(), (list, col) => { list.Add(col.ColumnName); return list; });
通常,Linq 允许从数据源检索和转换数据序列。 在这个问题中,您要做的是遍历一个序列并返回一个即时结果。 这不是 Linq 的主要关注点,但有一些方法可以执行这样的任务,包括 Aggregate()
、Average()
、Count()
、Max()
等。
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;
}
}
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说你缺少指定列的类型,即数据列。
List<string> columnList = (from DataColumn mycol in table.Columns select mycol.ColumnName).ToList();
在这里,这将是您的一行。
为什么不简单选择喜欢
DataTable table;
IEnumerable<string> header = from mycol in table.Columns.Cast<DataColumn>()
select mycol.ColumnName;
您遇到了一些问题,需要解决方法:
- ForEach 是 List specifict 方法,所以不能将其转换为 LINQ
- LINQ 用于数据选择、聚合,但不用于数据修改
-
table.Columns
,返回DataColumnCollection
,它不实现IEnumerable<T>
,所以无论如何你都必须强制转换它:var LINQheader = from mycol in table.Columns.Cast<DataColumn>() select name.ColumnName;