LINQ在多个属性上双向不同
本文关键字:属性 LINQ | 更新日期: 2023-09-27 18:26:59
我正在尝试通过对象列表的两个属性来过滤它。如果存在重复,则可以删除对象。如果第一个属性与第二个属性具有相同的值,而第二个特性与第一个属性具有同样的值。
示例:
object0: id0=1A, id1=2B
object1: id0=1A, id1=2B
object2: id0=1A, id1=3C
object3: id0=2B, id1=1A
object4: id0=2B, id1=3C
object5: id0=3C, id1=2B
因此,会发生以下情况:对象0删除对象1和对象3对象4删除对象5
最终输出:
object0: id0=1A, id1=2B
object2: id0=1A, id1=3C
object4: id0=2B, id1=3C
现在我有FOR循环来做这个,但我想知道是否有一种方法可以用linq来做这个?我尝试过使用Distinct、DistinctBy和GroupBy。我需要自己进行比较才能完成这项工作吗?
这样做。
source
.GroupBy(x => new {min = Math.Min(x.Id0, x.Id1), max = Math.Max(x.Id0, x.Id1)})
.Select(g => g.First());
经过测试。
public void SillyTuplesTest()
{
List<Tuple<string, int, int>> source = new List<Tuple<string, int, int>>()
{
Tuple.Create("object0", 1, 2),
Tuple.Create("object1",1, 2),
Tuple.Create("object2",1, 3),
Tuple.Create("object3",2, 1),
Tuple.Create("object4",2, 3),
Tuple.Create("object5",3, 2)
};
var result = source
.GroupBy(x => new { min = Math.Min(x.Item2, x.Item3), max = Math.Max(x.Item2, x.Item3) })
.Select(g => g.First());
foreach (Tuple<string, int, int> resultItem in result)
{
Console.WriteLine("{0} ({1}, {2})", resultItem.Item1, resultItem.Item2, resultItem.Item3);
}
}
结果
object0 (1, 2)
object2 (1, 3)
object4 (2, 3)
对于字符串,您可以使用:
source
.GroupBy(x =>
string.Compare(x.Id0, x.Id1, false) < 0 ?
new {min = x.Id0, max = x.Id1} :
new {min = x.Id1, max = x.Id0})
.Select(g => g.First());
如果有未知数量的字符串,可以使用HashSet<string>
作为键和SetComparer。
IEqualityComparer<HashSet<string>> comparer =
HashSet<string>.CreateSetComparer();
source
.GroupBy(x => new HashSet<string>(x.GetStrings()), comparer)
.Select(g => g.First());
创建一个扩展方法,例如:
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
var seenKeys = new HashSet<TKey>();
return source.Where(element => seenKeys.Add(keySelector(element)));
}
然后使用它。
看看这对你有什么好处。