我有两个列表如下,我怎么能说他们有相同的元素。订单并不重要。
var list1 = new List<int> {1,2,3};
var list2 = new List<int> {2,1,3};
我怎么能说这些是平等的?我应该编写自己的方法还是有内置的方法?
答案 0 :(得分:18)
这就是集合(例如,HashSet<T>
)的用途。集合没有已定义的顺序,SetEquals
验证集合和另一个集合是否包含相同的元素。
var set = new HashSet<int>(list1)
var equals = set.SetEquals(list2);
答案 1 :(得分:10)
您可以使用!Except
+ Any
:
bool list1InList2 = !list1.Except(list2).Any();
如果两者具有相同的项目但是list1包含在list2中(忽略重复项),则不会检查。
如果您想知道list2
中是否包含list1
,请使用:
bool list2InList1 = !list2.Except(list1).Any();
因此,如果您想确保两个列表包含相同的项目,则必须进行两项检查。
如果您还想考虑两个列表的大小相同,请预先检查list1.Count==list2.Count
。
但是,如果使用set方法(参见Harald's comment),此检查无用,如果之后忽略重复项,则比较计数没有多大意义。
一般来说,HashSet<T>
有一些很好而有效的方法来检查两个序列是否具有相同的项目(忽略重复项),dcastro already showed一个。
如果您想要一个有效的解决方案来确定两个列表是否包含相同的项目,相同计数和不忽略重复,但忽略订单 (否则使用SequenceEquals
):
public static bool SequenceEqualsIgnoreOrder<T>(this IEnumerable<T> list1, IEnumerable<T> list2, IEqualityComparer<T> comparer = null)
{
if(list1 is ICollection<T> ilist1 && list2 is ICollection<T> ilist2 && ilist1.Count != ilist2.Count)
return false;
if (comparer == null)
comparer = EqualityComparer<T>.Default;
var itemCounts = new Dictionary<T, int>(comparer);
foreach (T s in list1)
{
if (itemCounts.ContainsKey(s))
{
itemCounts[s]++;
}
else
{
itemCounts.Add(s, 1);
}
}
foreach (T s in list2)
{
if (itemCounts.ContainsKey(s))
{
itemCounts[s]--;
}
else
{
return false;
}
}
return itemCounts.Values.All(c => c == 0);
}
用法:
var list1 = new List<int> { 1, 2, 3, 1 };
var list2 = new List<int> { 2, 1, 3, 2 };
bool sameItemsIgnoringOrder = list1.SequenceEqualsIgnoreOrder(list2);
// false because same count and same items but 1 appaears twice in list1 but once in list2
如果订单很重要且重复数也一样,请使用:
bool sameItemsSameOrder = list1.SequenceEqual(list2);
答案 2 :(得分:1)
不使用linq。
private static bool AreListsEqual(List<int> list1, List<int> list2)
{
var areListsEqual = true;
if (list1.Count != list2.Count)
return false;
for (var i = 0; i < list1.Count; i++)
{
if (list2[i] != list1[i])
{
areListsEqual = false;
}
}
return areListsEqual;
}
答案 3 :(得分:0)