C#LINQ三元运算符作为switchcase里面的一个foreach

问题描述:

我使用LINQ和HtmlAgilitypack来创建一个HTML外的数据表。 下面获取HTML表格的标题和构建数据表列:C#LINQ三元运算符作为switchcase里面的一个foreach

var nodes = htmlDoc.DocumentNode.SelectNodes("//table[@class='ps-sellers-table crts']/tr"); 
      nodes[0].Elements("th") 
      .Skip(0) 
      .Select(th => th.InnerText 
      .Trim()) 
      .ToList() 
      .ForEach(header => dt.Columns.Add(header)); 

到目前为止它的工作完全不同的,我需要一些定制。

  1. 选择要添加的列。
  2. 并指定列类型。

这个SELECT语句会做两件事情上面:

switch (header) 
      { 
       case ("id") : dt.Columns.Add(header,typeof(int)); break; 
       case ("name") : dt.Columns.Add(header,typeof(string)); break; 
       case ("price") : dt.Columns.Add(header,typeof(decimal)); break; 
       case ("shipping") : dt.Columns.Add(header,typeof(decimal)); break; 
       default : //skip the column and dont add it 
      } 

但是我真的很新的LINQ和C#,我想实现在foreach内部的上述开关的情况下在第一个片段,我知道我应该使用ternary operator,但我不确定这个sytax。

+5

为什么不写一个使用开关块并调用方法的方法呢? – 2013-03-05 20:57:47

+5

我同意torrential,过度滥用三元运算符使代码混乱,几乎不可读。包含逻辑的方法更具可读性(如果公开,则可测试)。我个人只使用布尔运算符作为三元运算符。 – 2013-03-05 20:59:22

+3

它看起来像是在列名和类型之间有一个简单的映射。为什么不使用“字典”? – 2013-03-05 21:03:57

我会将开关包装到一个方法中,然后从您的select语句中调用该方法。

我的版本会是什么样子:

var nodes = htmlDoc.DocumentNode.SelectNodes("//table[@class='ps-sellers-table crts']/tr"); 
     nodes[0].Elements("th") 
     .Select(th => th.InnerText.Trim()); 

foreach(var node in nodes) 
    AddColumnToDataTable(node, dt); 

注意,有没有必要Skip(0),并呼吁ToList()只是使用降低可读性和增加开销。我个人更喜欢使用正常的foreach

这就是说,你的方法可以被重构为使用Dictionary<string, Type>来代替。如果您添加到您的类:

Dictionary<string, Type> typeLookup; 
// In your constructor: 

public YourClass() 
{ 
    typeLookup.Add("id", typeof(int)); 
    typeLookup.Add("name", typeof(string)); 
    typeLookup.Add("price", typeof(decimal)); 
    typeLookup.Add("shipping", typeof(decimal)); 
} 

然后,您可以写你的方法:

void AddColumnToDataTable(string columnName, DataTable table) 
{ 
    table.Columns.Add(columnName, typeLookup[columnName]); 
} 
+0

你可以直接在'IEnumerable'上使用'Aggregate(dt,(table,header)=> dt.Columns.Add(header))'来避免'ToList'调用的混淆 – 2013-03-05 21:24:37

+1

@ just.another.programmer I无论如何都避免了“ToList”调用。一般来说,我喜欢避免执行副作用的LINQ语句 - 在LINQ查询中对任何方法(如“添加”)的任何调用都会导致不良习惯的尖叫......也就是说,如果您想要使用“Aggregate”这样做 - 一个简单的'选择'也可以工作... – 2013-03-05 21:27:26

+0

只是一个小问题,关于忽略使用where子句的列,以下是好吗? 'nodes [0] .Elements(“th”)。Select(th => th.InnerText.Trim())。where(th => th!=“somecolumn”);' – user1590636 2013-03-05 22:22:59

你可以切换只需添加到在foreach,不知道为什么你必须使用三元运算

.ToList().ForEach(header => 
{ 
    switch (header) 
    { 
     case ("id"): dt.Columns.Add(header, typeof(int)); break; 
     case ("name"): dt.Columns.Add(header, typeof(string)); break; 
     case ("price"): dt.Columns.Add(header, typeof(decimal)); break; 
     case ("shipping"): dt.Columns.Add(header, typeof(decimal)); break; 
     default: break; //skip the column and dont add it 
    } 
});