与新的.NET 6、7等类似,我们有一个lists类。
List<int> A = new List<int>();
List<int> B = new List<int>();
List<int> C = A.Except(B).ToList();我的问题是,如何最好地使用同一个类的字符串版本:
string A = "<div><p>One</p><p>Two</p></div>";
string B = "<div><p>One</p><p>Two</p><p>Three</p></div>";
string C = A.Except(B).ToString();得到结果= <p>Three</p>
相反,我得到了:
System.Linq.Enumerable+<ExceptIterator>d__73`1[System.Char]我做错了什么?
编辑:
只需将最大的字符串用于,除了最小的字符串外,倒转数组顺序:
string C = B.Except(A);使用:尼克氏 new string(C.ToArray());给我:
hr在使用相反的方法后稍微没有预料到的结果。
发布于 2019-01-10 15:05:56
你的解决方案有两个问题。
ToString()的行为
当在.ToString()上执行IEnumerable时,它总是打印出类型。这是因为IEnumerable不覆盖ToString()的行为。有关此问题的更多信息,请参见ToString。
如果要将IEnumerable (返回类型的以外)转换为字符串,则必须执行以下操作
var C = new string(A.Except(B));A.Except(B)的行为
除了方法不像你想的那样起作用。
例如,下面的代码:
var a = new List<int> { 1, 2, 3 };
var b = new List<int> { 2, 3, 4 };
var c = a.Except(b);其结果是{1 }。该方法有效地返回a中的所有in的新枚举,而不是b中的枚举。
现在,字符串只是字符的枚举-更准确地说,
var A = "<div><p>One</p><p>Two</p></div>";从LINQ的角度来看,相当于
var A = new List<char> { '<', 'd', 'i', 'v', '>', ..., '<', '/', 'd', 'i', 'v', '>' };B也是如此。
所以,当您执行A.Except( B )时,LINQ实际上要做的是遍历每个字符,看看它是否能在B中找到它。如果可以,它不会在结果集中结束。现在,由于A中的所有字符都在B中,所以您将得到一个空字符串。要了解实际情况,只需稍微修改A,使其包含一个不在B中的字符:
string A = "<div><p>One</p><p>Two</p></div>ApplePie";如果你现在做了
string A = "<div><p>One</p><p>Two</p></div>ApplePie";
string B = "<div><p>One</p><p>Two</p><p>Three</p></div>";
string C = new string(A.Except(B).ToArray());你会得到"AlP“。
解决方案
在我看来,执行best的最佳方法是解析字符串,将它们转换为对象,然后执行best。没有内置的算法能够分辨您的字符串实际上是结构化的,以及如何区分它们。作为一种有效的解决方案,使用HtmlAgilityPack ( nuget包)
var docB = new HtmlDocument();
docB.LoadHtml(B);
var docA = new HtmlDocument();
docA.LoadHtml(A);
var nodes = docB.DocumentNode.FirstChild.Descendants("p").Select(node => node.InnerHtml)
.Except(docA.DocumentNode.FirstChild.ChildNodes.Select(node => node.InnerHtml));
// take note that we are actually doing whatIsInB.Except(whatIsInA), since doing the reverse would result in nothing. There is no <p> in A that is not also present in B
var result = string.Join(Environment.NewLine, nodes); // will resut in "Three"
var otherResult = $"<p>{result}</p>"; // "<p>Three</p>"我让你做一个更一般的方法:)
但这个想法是,如果你想工作,除了你期望的方式,你将不得不要求它使用字符串,而不是字符。
是否按照其他解决方案的建议,使用HtmlAgilityPack或Regex进行字符串组件(本例中的元素)提取所需的解析,完全取决于您。
发布于 2019-01-10 14:43:40
使用以外()扩展方法时,返回类型是Char的列表。
而且,A.Excepts(B)永远不会产生您想要的结果,因为它将字符串转换为char数组。因此,它将从B中存在的A中删除每一个字符。
你需要想一种不同的算法来做到这一点。
发布于 2019-01-10 14:57:09
您想要的Wnat不是Except,因为它是一个称为集合差或相对补码的集合操作,在这个操作中,您说您希望一个集合中的元素不存在于另一个集合中。
您可以使用正则表达式组实现您期望的结果:
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
// Input string.
string input = "<div><p>One</p><p>Two</p><p>Three</p></div>";
// Use named group in regular expression.
Regex expression = new Regex(@"^<div><p>One</p><p>Two</p>(?<middle>[<>/\w]+)</div>$");
// See if we matched.
Match match = expression.Match(input);
if (match.Success)
{
// Get group by name.
string result = match.Groups["middle"].Value;
Console.WriteLine("Middle: {0}", result);
}
// Done
Console.ReadLine();
}
}使用正则表达式^<div><p>One</p><p>Two</p>(?<middle>[<>/\w]+)</div>$,您可以说字符串应该以<div><p>One</p><p>Two</p>开头(^),用</div>结束($),并且无论在包含<、E 113>E 214、E 115/E 216或任何字母数字字符(E 117\wE 218)之间的任何字符(E 119+E 220),都将被添加到名为E 121E<222>代码的组中。
不过,我不推荐你去尝试用regex解析HTML.
https://stackoverflow.com/questions/54130981
复制相似问题