C# 基于Linq查询中的属性值过滤出重复的元素
我使用Linq尝试过滤掉任何重复的元素,这些元素对于“name”属性具有相同的值 原始xml:C# 基于Linq查询中的属性值过滤出重复的元素,c#,linq,filter,duplicates,xelement,C#,Linq,Filter,Duplicates,Xelement,我使用Linq尝试过滤掉任何重复的元素,这些元素对于“name”属性具有相同的值 原始xml: <foo> <property name="John" value="Doe" id="1" /> <property name="Paul" value="Lee" id="1" /> <property name="Ken" value="Flow" id="1" /> <property name="Jane" value="Horace"
<foo>
<property name="John" value="Doe" id="1" />
<property name="Paul" value="Lee" id="1" />
<property name="Ken" value="Flow" id="1" />
<property name="Jane" value="Horace" id="1" />
<property name="Paul" value="Lee" id="1" />
... other xml properties with different id's
</foo>
不幸的是,筛选步骤不起作用。我认为Where()过滤器会检查当前元素之前具有相同属性名的任何元素,然后将其包含在大于零的集合中,从而排除当前元素(称为“f”),但这不会发生。想法?您的方法有点奇怪,例如,您不需要将元素投射到新元素中;当您将现有元素添加到新文档时,它只起作用(tm) 我只需通过
name
属性对
元素进行分组,然后从每组中选择第一个元素:
var doc = XDocument.Parse(@"<foo>...</foo>");
var result = new XDocument(new XElement("foo",
from property in doc.Root
group property by (string)property.Attribute("name") into g
select g.First()));
var doc=XDocument.Parse(@“…”);
var结果=新XDocument(新XElement(“foo”),
来自doc.Root中的属性
按(字符串)property.Attribute(“名称”)将属性分组为g
选择g.First());
我认为您应该先删除重复项,然后再进行投影。例如:
var uniqueProps = from property in doc.Root
group property by (string)property.Attribute("name") into g
select g.First() into f
select new XElement("property",
new XAttribute("name", f.Attribute("name").Value),
f.Attribute("value"));
或者,如果您更喜欢方法语法
var uniqueProps = doc.Root
.GroupBy(property => (string)property.Attribute("name"))
.Select(g => g.First())
.Select(f => new XElement("property",
new XAttribute("name", f.Attribute("name").Value),
f.Attribute("value")));
您只需创建一个IEqualityComparer与Distinct()一起使用,就可以得到您所需要的
class Program
{
static void Main(string[] args)
{
string xml = "<foo><property name=\"John\" value=\"Doe\" id=\"1\"/><property name=\"Paul\" value=\"Lee\" id=\"1\"/><property name=\"Ken\" value=\"Flow\" id=\"1\"/><property name=\"Jane\" value=\"Horace\" id=\"1\"/><property name=\"Paul\" value=\"Lee\" id=\"1\"/></foo>";
XElement x = XElement.Parse(xml);
var a = x.Elements().Distinct(new MyComparer()).ToList();
}
}
class MyComparer : IEqualityComparer<XElement>
{
public bool Equals(XElement x, XElement y)
{
return x.Attribute("name").Value == y.Attribute("name").Value;
}
public int GetHashCode(XElement obj)
{
return obj.Attribute("name").Value.GetHashCode();
}
}
类程序
{
静态void Main(字符串[]参数)
{
字符串xml=”“;
XElement x=XElement.Parse(xml);
var a=x.Elements().Distinct(新的MyComparer()).ToList();
}
}
班级比较:IEqualityComparer
{
公共布尔等于(像素x,像素y)
{
返回x.Attribute(“name”).Value==y.Attribute(“name”).Value;
}
公共整数GetHashCode(XElement obj)
{
返回obj.Attribute(“name”).Value.GetHashCode();
}
}
投影用于所需代码的另一部分。我必须在那里扮演那个角色,很有趣。简单而优雅!谢谢,我喜欢这个方法(并使用了它),因为它更容易实现,而不需要改变我的分组逻辑。我很好奇为什么我原来的方法不起作用。
class Program
{
static void Main(string[] args)
{
string xml = "<foo><property name=\"John\" value=\"Doe\" id=\"1\"/><property name=\"Paul\" value=\"Lee\" id=\"1\"/><property name=\"Ken\" value=\"Flow\" id=\"1\"/><property name=\"Jane\" value=\"Horace\" id=\"1\"/><property name=\"Paul\" value=\"Lee\" id=\"1\"/></foo>";
XElement x = XElement.Parse(xml);
var a = x.Elements().Distinct(new MyComparer()).ToList();
}
}
class MyComparer : IEqualityComparer<XElement>
{
public bool Equals(XElement x, XElement y)
{
return x.Attribute("name").Value == y.Attribute("name").Value;
}
public int GetHashCode(XElement obj)
{
return obj.Attribute("name").Value.GetHashCode();
}
}