[英]c# get difference between two lists that use structs
这是我的第一篇文章。 我在C#中相当陌生,并且正在尝试使用结构类型的列表。
public struct MyStruct
{
public string Field1;
public string Field2;
}
List<MyStruct> BigList = new List<MyStruct> { };
List<MyStruct> SmallList = new List<MyStruct> { };
到目前为止,我所做的一切都使用了已知的类型(例如,字符串),但是对于上面示例中的列表,我无法使用任何具有肯定结果的函数。
目前,其想法是获得使用该结构类型(列表)的两个列表之间的差异。 BigList将始终具有比Small列表更多的项目,其想法是考虑到Field1,在SmalList中查找BigList中不存在的所有项目。 理想情况下,结果可以是相同类型的列表(列表)。
这可能吗? 我已经尝试了一些在stackoverflow中找到的示例,但是找不到许多使用结构列表的示例,而我尝试过的示例却无效。
一个适用于字符串列表的示例:
var Missing = BigList.Except(SmallList).ToList()
可能是一个解决方案,但我需要查看一个字段(结构的Field1),而不仅仅是一个简单的字符串。
对于这些类型的列表,使用.Sort或.Contains不能产生肯定的结果(专门查看结构的一个字段,例如List)。
有人能帮我吗? 那很好啊!
提前致谢。 问候,
就像其他人所说的,在您的示例中使用struct尤其是由于您是C#的新手,可能不是真正的好主意,而是更多的错误。 我建议您用一个类替换您的结构。
您面临的问题是,因为您使用的是自己定义的类型,所以比较将无法正常工作,或者至少无法正常工作。
它不会知道如何比较两个对象,如果是类,则将验证它是否是同一对象,如果是结构,则将进行字节对字节的比较(如果该结构不包含引用类型)或比较它包含的引用是否相同(如果结构包含引用类型)。
使一切正常工作所需要做的是重写类中的Equals
方法。 请参阅此MSDN文章以开始使用它: https : //msdn.microsoft.com/zh-cn/library/336aedhh(v=vs.100).aspx 。
另外,您可以为您的类型实现IEqualityComparer。 如果您无权访问类实现,则它特别有用。 检查此MSDN文章以执行此操作: https : //msdn.microsoft.com/zh-cn/library/bb300779(v=vs.110).aspx
有很多方法可以解决此问题。 这是一种非常有表现力的方法,可以使用Field1
查找BigList
元素, BigList
元素没有等效的SmallList
。
var bigListWithoutSmallList =
BigList.Where( b => !SmallList.Any( x => x.Field1 == b.Field1 ));
注意:使用class
或struct
与您的问题无关。
一种解决方案是实现IEquatable<MyStruct>
class Program
{
static void Main(string[] args)
{
var smallList = new List<MyStruct>() { new MyStruct
{
Field1="1f",
Field2 ="2f"
},
new MyStruct
{
Field1="2f",
Field2 ="22f"
}};
var bigList = new List<MyStruct>() { new MyStruct
{
Field1="1f",
Field2 ="2f"
},
new MyStruct
{
Field1="3 f",
Field2 ="22f"
},new MyStruct
{
Field1="4f",
Field2 ="22f"
}
};
//find the difference
var diffList = smallList.Except(bigList);
}
public struct MyStruct:IEquatable<MyStruct>
{
public string Field1;
public string Field2;
public bool Equals(MyStruct other)
{
if (this.Field1==other.Field1 && this.Field2==other.Field2)
{
return true;
}
return false;
}
public override int GetHashCode()
{
return Field1.GetHashCode() & Field2.GetHashCode();
}
public override bool Equals(object obj)
{
return this.Equals(obj);
}
}
}
结果可能是带有
new MyStruct
{
Field1="2f",
Field2 ="22f"
}};
有一个名为MoreLINQ的开源库,它提供了一个扩展方法,称为IEnumerable<T>
ExceptBy
, ExceptBy
您的需要。
ExceptBy
具有以下签名:
public static IEnumerable<TSource> ExceptBy<TSource, TKey>(
this IEnumerable<TSource> first,
IEnumerable<TSource> second,
Func<TSource, TKey> keySelector);
键选择器是将源值映射到用于比较的键值的函数,但是结果仍然是TSource
的序列。
在您的情况下,将这样调用:
var Missing = BigList
.ExceptBy(SmallList, (item => item.fieldToCompareBy)
.ToList();
与在Where
子句中使用Contains
或Any
相比,此方法具有相当好的性能。 它只需要立即遍历second
序列一次,然后就可以懒惰地从第first
序列中获取结果流。
如果仅在结构中覆盖Equals,则Except将起作用。 诀窍是您需要在内部将其视为Nullable。
class Program
{
static void Main(string[] args)
{
var smallList = new List<MyStruct>()
{
new MyStruct { Field1="1f", Field2 ="2f" },
new MyStruct { Field1="2f", Field2 ="22f" }
};
var bigList = new List<MyStruct>()
{
new MyStruct { Field1="1f", Field2 ="2f" },
new MyStruct { Field1="3f", Field2 ="22f" },
new MyStruct { Field1="4f", Field2 ="22f" }
};
var result = bigList.Except(smallList);
Console.ReadLine();
}
}
public struct MyStruct
{
public string Field1;
public string Field2;
public override bool Equals(object obj)
{
return Field1 == (obj as Nullable<MyStruct>).Value.Field1;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.