将这两个表达式合并为一个LINQ表达式

本文关键字:表达式 一个 LINQ 两个 合并 | 更新日期: 2023-09-27 18:06:41

我使用HTMLAgilityPack来解析一些html。当使用和xpath查询与linq查询相结合时,我得到了我期望的结果集。是否有一种方法,我可以将它们结合到一个单一的LINQ查询?

var test = doc.DocumentNode.SelectNodes("//div[@class='product']");
foreach (var item in test)
{
    var result = from input in item.Descendants("span")
                 where input.Attributes["class"].Value == "Bold"
                 where input.InnerHtml.ToUpper() == "GetItem"
                 select input;   
    return result;           
}

将这两个表达式合并为一个LINQ表达式

如果你想收集所有的跨度在一起(如果我是正确的假设这就是你想要的)…

我首先将其转换为更流畅的符号(我发现SelectMany更容易掌握这种方式-但这只是我)

(免责声明:我是从记忆中写的,复制/粘贴你的代码-目前不是由VS -你需要检查,让它写如果有任何问题-但我认为我得到了它或多或少)

var test = doc.DocumentNode.SelectNodes("//div[@class='product']");
foreach(var item in test)
    item.Descendants("span").Where(input => input.Attributes["class"].Value == "Bold").Where(input => input.InnerHtml.ToUpper() == "GetItem").Select(input => input);

最后……

var allSpans = doc.DocumentNode.SelectNodes("//div[@class='product']")
    .SelectMany(item => item.Descendants("span").Where(input => input.Attributes["class"].Value == "Bold").Where(input => input.InnerHtml.ToUpper() == "GetItem"));

…或者沿着这些行

只是想向您展示在Linq中执行SelectMany的另一种方法。这是一种风格选择,SO中的许多人更喜欢. selectmany扩展方法,因为他们可以看到Monad是如何应用于IEnumerable的。我更喜欢这种方法,因为它更接近函数式编程模型。

return from product in doc.DocumentNode.SelectNodes("//div[@class='product']")
       from input in product.Descendants("span")
       where input.Attributes["class"].Value == "Bold"
       where input.InnerHtml.ToUpper() == "GetItem"
       select input;        
return (
    from result in 
        from item in doc.DocumentNode.SelectNodes("//div[@class='product']")
        from input in item.Descendants("span")
        where input.Attributes["class"].Value == "Bold"
        where input.InnerHtml.ToUpper() == "GetItem"
        select input
    select result
    ).First();

如果你真的想在一个查询中包含所有内容,你可以这样做:

var result = doc.DocumentNode.SelectNodes("//div[@class='product']")
    .SelectMany(e => e.Descendants("span")
        .Where(x => x.Attributes["class"].Value == "Bold" && 
                    x.InnerHtml.ToUpper() == "GetItem"))
    .ToList();
return result;

为了便于阅读,我建议间隔一些,更像这样:

var result = new List<SomeType>();
var nodes = doc.DocumentNode.SelectNodes("//div[@class='product']");
nodes.SelectMany(e => e.Descendants("span")
    .Where(x => x.Attributes["class"].Value == "Bold" && 
                x.InnerHtml.ToUpper() == "GetItem"));
return result.ToList();

SelectMany()方法将内部查询的结果平铺成单个IEnumerable<T>