C# Linq以非常规方式删除ASP.NET WEB API中的重复项
这是我的模型:C# Linq以非常规方式删除ASP.NET WEB API中的重复项,c#,linq,select,asp.net-web-api,C#,Linq,Select,Asp.net Web Api,这是我的模型: public class Combination { public int Id { get; set; } public int CombOne{ get; set; } public int CombTwo{ get; set; } } 我想编写一个LINQ语句来提取Combination类的实例,该类包含属性CombOne和CombTwo的重复组合。 因此,如果有以下三种情况: Combination C1= new Combination{I
public class Combination
{
public int Id { get; set; }
public int CombOne{ get; set; }
public int CombTwo{ get; set; }
}
我想编写一个LINQ语句来提取Combination类的实例,该类包含属性CombOne和CombTwo的重复组合。
因此,如果有以下三种情况:
Combination C1= new Combination{Id=1, CombOne=1, CombTwo=2};
Combination C2= new Combination{Id=2, CombOne=2, CombTwo=1};
Combination C3= new Combination{Id=3, CombOne=1, CombTwo=2};
Linq语句应该返回C2和C3的列表,因为它们包含CombOne和CombTwo变量的重复组合,同时应该保留原始实例(C1)(不应该返回C1,因为它是该组合的第一个实例。)
我用foreach循环得到了正确的结果
List<Combination> invalid2 = new List<Combination>();
foreach (Combination g in list)// Gamelist.Match is a list of Combination type
{
if (invalid2.Contains(g))
continue;
List<Combination> invalid3 = (from r in list
where
((r != g) &&
(((r.CombOne == g.CombOne) && (r.CombTwo == g.CombTwo)) ||
((r.CombOne == g.CombTwo) && (r.CombTwo == g.CombOne))))
select r).ToList();
invalid2 = invalid2.Concat(invalid3).ToList();
}
List invalid2=新列表();
foreach(列表中的组合g)//Gamelist.Match是组合类型的列表
{
如果(无效2.包含(g))
继续;
列表无效3=(从列表中的r开始)
哪里
((r!=g)&&
((r.CombOne==g.CombOne)和&(r.CombTwo==g.CombTwo))||
((r.CombOne==g.CombTwo)和&(r.CombTwo==g.CombOne)))
选择r.ToList();
invalid2=invalid2.Concat(invalid3.ToList();
}
我希望只使用Linq语句来获得结果,以提高效率。我试了很多,但没有得到想要的结果。提前感谢您的真诚努力如果我理解正确,您希望输出生成包含以前见过的集合{CombOne,CombTwo}的任何实例。这意味着某种聚合。要做到这一点,您需要跟踪以前看到的实例,并引用该集合,以确保所检查的每个后续元素都尚未看到。我将利用
Hashet.Add
不添加已存在于集合中的元素的事实,并使用自定义比较器在HashSet
中实现相等
var set = new HashSet<Combination>(new CombinationComparer());
var invalid = list.Aggregate(new List<Combination>(list.Count),
(a,c) =>
{
if (!set.Add(c))
{
a.Add(c);
}
return a;
});
我在invalid2=(来自GameList.Match中的r)创建了一个工作小提琴
来自游戏列表中的g。匹配
在哪里((r.IdI猜测hashset只有在实例不相等时才会消除它们。这里我试图列出组合类型的对象,每个对象都有一个唯一的Id。因此我认为它不会消除任何组合实例。@Sreeraj-您忽略了一个事实,即使用比较器定义相等,而不是对象的equals方法。Accor对比较器来说,如果是同一个对象,它们是相等的。根据你的标准,它们都是空的,或者它们的Comb*
匹配。为什么xor不是可交换的?@KonradRudolph是的,我可以使用xor。我的借口是我还没有喝咖啡。:)通常我会乘以素数,这就是我想说的,除了在这种情况下,我们希望它们是可交换的,但仍然不会在(x,x)(y,y)上碰撞。这是非常低效的-O(n^2),因为你在列表中的每个元素上迭代列表一次。我使用哈希集和自定义比较器的解决方案是O(n)(或者比你的快n倍)。你至少应该试试我的解决方案,看看它是否有效。
public class CombinationComparer : IEqualityComparer<Combination>
{
public bool Equals(Combination c1, Combination c2)
{
if (ReferenceEquals(c1,c2))
{
return true;
}
if (c1 == null || c2 == null)
{
return false;
}
return (c1.CombOne == c2.CombOne && c1.CombTwo == c2.CombTwo)
|| (c1.CombOne == c2.CombTwo && c1.CombTwo == c2.CombOne);
}
public int GetHashCode(Combination c)
{
if (c == null)
{
return 0;
}
unchecked
{
// it's important that this be commutative so we don't
// do the usual multiply by a prime to differentiate
// them.
return CombOne.GetHashCode() + CombTwo.GetHashCode();
}
}
}
var set = new HashSet<Combination>(new CombinationComparer());
var invalid = new List<Combination>(list.Count);
foreach (var item in list)
{
if (set.Add(item)) continue;
invalid.Add(item);
}
var unique = list.Distinct(new CombinationComparer());
invalid2= (from r in GameList.Match
from g in GameList.Match
where((r.Id<g.Id)&&(((r.TeamAId == g.TeamAId) && (r.TeamBId == g.TeamBId)) || ((r.TeamAId == g.TeamBId) && (r.TeamBId == g.TeamAId))))
select g).Distinct().ToList();