如何最有效地测试,如果两个数组包含在C#相当于项目 [英] How to most efficiently test if two arrays contain equivalent items in C#
问题描述
我有两个数组,我想知道他们是否包含相同的项目。 等于(obj对象)
不起作用,因为数组是引用类型。我已经张贴了我下面的尝试,但因为我敢肯定,这是一个共同的任务,我想知道是否有一个更好的测试。
公共BOOL ContainsEquivalentSequence< T>(T []数组1,T []数组2)
{
布尔a1IsNullOrEmpty =的ReferenceEquals(数组1,NULL)|| array1.Length == 0;
布尔a2IsNullOrEmpty =的ReferenceEquals(数组2,NULL)|| array2.Length == 0;
如果(a1IsNullOrEmpty)返回a2IsNullOrEmpty;
如果(a2IsNullOrEmpty || array1.Length = array2.Length!)返回false;
的for(int i = 0; I< array1.Length;我++)
如果(!等于(数组1 [I]中,数组2 [I]))
返回false;
返回true;
}
更新 - System.Linq.Enumerable.SequenceEqual是不是更好
我反映的来源和它的不长执行循环之前比较。这是有道理的,因为该方法一般设计为的IEnumerable< T>
,而不是一个 T []
。
公共静态布尔SequenceEqual< TSource>(这个IEnumerable的< TSource>首先,IEnumerable的< TSource>第二个,的IEqualityComparer< TSource>比较器)
{
如果(比较器== NULL)
{
比较器= EqualityComparer< TSource> .DEFAULT;
}
如果(第一== NULL)
{
扔Error.ArgumentNull(第一);
}
如果(二== NULL)
{
扔Error.ArgumentNull(第二);
}
使用(IEnumerator的< TSource>枚举= first.GetEnumerator())
{
使用(IEnumerator的< TSource> enumerator2 = second.GetEnumerator())
{
而(enumerator.MoveNext())
{
如果(!enumerator2.MoveNext()||!comparer.Equals(enumerator.Current,enumerator2.Current))
{
返回false;
}
}
如果(enumerator2.MoveNext())
{
返回false;
}
}
}
返回true;
}
我已经用做了一些测试,任何
,包含
,所有
和 SequenceEqual
然后,我选择了最好的3。
有不同输入不同的结果...
100大小的两个相同的数组: SequenceEqual
也较快
[SequenceEqual:00:00:00.027] *
[ContainsEqSeq:00:00:00.046]
[并行:00:00:00.281]
1000大小的两个相同的数组: SequenceEqual
也较快
[SequenceEqual:00:00:00.240] *
[ContainsEqSeq:00:00:00.361]
[并行:00:00:00.491]
10000大小的两个相同的数组:并行
也较快
[SequenceEqual:00:00:02.357]
[ContainsEqSeq:00:00:03.341]
[并行:00:00:01.688] *
50000大小的两个相同的数组:并行
踢屁股
[SequenceEqual:00:00:11.824]
[ContainsEqSeq:00:00:17.206]
[并行:00:00:06.811] *
两个阵列,但有一点不同在位置200: SequenceEqual
也较快
[SequenceEqual:00:00:00.050] *
[ContainsEqSeq:00:00:00.075]
[并行:00:00:00.332]
两个阵列,但有一点不同位置0: ContainsEqSeq
和 SequenceEqual
为快
[SequenceEqual:00:00:00.002] *
[ContainsEqSeq:00:00:00.001] *
[并行:00:00:00.211]
两个阵列,但有一点不同位置999: SequenceEqual
也较快
[SequenceEqual:00:00:00.237] *
[ContainsEqSeq:00:00:00.330]
[并行:00:00:00.691]
两个阵列,但有一点不同的位置9999:并行
踢屁股
[SequenceEqual:00:00:02.386]
[ContainsEqSeq:00:00:03.417]
[并行:00:00:01.614] *
在code为 SequenceEqual
是
a1.SequenceEqual(A2)
在code为 ContainsEqSeq
是你的方法。
在code为并行
是
布尔a1IsNullOrEmpty =的ReferenceEquals(A1,NULL)|| a1.Length == 0;
布尔a2IsNullOrEmpty =的ReferenceEquals(A2,NULL)|| a2.Length == 0;
如果(a1IsNullOrEmpty)返回a2IsNullOrEmpty;
如果(a2IsNullOrEmpty || a1.Length = a2.Length!)返回false;VAR areEqual = TRUE;
Parallel.ForEach(A1,
(I,S,X)=>
{
如果(A1 [X]!= A2 [X])
{
areEqual = FALSE;
s.Stop();
}
});返回areEqual;
我要说的是最好的一个取决于你输入的是什么。
如果您将与巨大的阵列的工作(如10000+)我会说并行
是最好的选择,它只有当上一开始就失去了差异
有关其他案件 SequenceEqual
可能是最好的一个,我只能用 INT []
测试过,但我相信,它可以快速与复杂类型为好。
但请记住,结果将相应变化的输入。
I have two arrays and I want to know if they contain the same items. Equals(object obj)
doesn't work because an array is a reference type. I have posted my attempt below, but since I'm sure this is a common task I'd like to know if there is a better test.
public bool ContainsEquivalentSequence<T>(T[] array1, T[] array2)
{
bool a1IsNullOrEmpty = ReferenceEquals(array1, null) || array1.Length == 0;
bool a2IsNullOrEmpty = ReferenceEquals(array2, null) || array2.Length == 0;
if (a1IsNullOrEmpty) return a2IsNullOrEmpty;
if (a2IsNullOrEmpty || array1.Length != array2.Length) return false;
for (int i = 0; i < array1.Length; i++)
if (!Equals(array1[i], array2[i]))
return false;
return true;
}
Update - System.Linq.Enumerable.SequenceEqual is not better
I reflected the source and it does not compare the length prior to executing the loop. This makes sense since the method is designed generally for an IEnumerable<T>
, not for a T[]
.
public static bool SequenceEqual<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
if (comparer == null)
{
comparer = EqualityComparer<TSource>.Default;
}
if (first == null)
{
throw Error.ArgumentNull("first");
}
if (second == null)
{
throw Error.ArgumentNull("second");
}
using (IEnumerator<TSource> enumerator = first.GetEnumerator())
{
using (IEnumerator<TSource> enumerator2 = second.GetEnumerator())
{
while (enumerator.MoveNext())
{
if (!enumerator2.MoveNext() || !comparer.Equals(enumerator.Current, enumerator2.Current))
{
return false;
}
}
if (enumerator2.MoveNext())
{
return false;
}
}
}
return true;
}
I've done some tests using Any
, Contains
, All
and SequenceEqual
then I picked the best 3.
There are different results for different inputs...
Two identical arrays of size 100: SequenceEqual
was faster
[ SequenceEqual: 00:00:00.027 ]*
[ ContainsEqSeq: 00:00:00.046 ]
[ Parallel: 00:00:00.281 ]
Two identical arrays of size 1000: SequenceEqual
was faster
[ SequenceEqual: 00:00:00.240 ]*
[ ContainsEqSeq: 00:00:00.361 ]
[ Parallel: 00:00:00.491 ]
Two identical arrays of size 10000: Parallel
was faster
[ SequenceEqual: 00:00:02.357 ]
[ ContainsEqSeq: 00:00:03.341 ]
[ Parallel: 00:00:01.688 ]*
Two identical arrays of size 50000: Parallel
kick ass
[ SequenceEqual: 00:00:11.824 ]
[ ContainsEqSeq: 00:00:17.206 ]
[ Parallel: 00:00:06.811 ]*
Two arrays with one difference at position 200: SequenceEqual
was faster
[ SequenceEqual: 00:00:00.050 ]*
[ ContainsEqSeq: 00:00:00.075 ]
[ Parallel: 00:00:00.332 ]
Two arrays with one difference at position 0: ContainsEqSeq
and SequenceEqual
were faster
[ SequenceEqual: 00:00:00.002 ]*
[ ContainsEqSeq: 00:00:00.001 ]*
[ Parallel: 00:00:00.211 ]
Two arrays with one difference at position 999: SequenceEqual
was faster
[ SequenceEqual: 00:00:00.237 ]*
[ ContainsEqSeq: 00:00:00.330 ]
[ Parallel: 00:00:00.691 ]
Two arrays with one difference at position 9999: Parallel
kick ass
[ SequenceEqual: 00:00:02.386 ]
[ ContainsEqSeq: 00:00:03.417 ]
[ Parallel: 00:00:01.614 ]*
The code for SequenceEqual
is
a1.SequenceEqual(a2)
The code for ContainsEqSeq
is your method.
The code for Parallel
is
bool a1IsNullOrEmpty = ReferenceEquals(a1, null) || a1.Length == 0;
bool a2IsNullOrEmpty = ReferenceEquals(a2, null) || a2.Length == 0;
if (a1IsNullOrEmpty) return a2IsNullOrEmpty;
if (a2IsNullOrEmpty || a1.Length != a2.Length) return false;
var areEqual = true;
Parallel.ForEach(a1,
(i, s, x) =>
{
if (a1[x] != a2[x])
{
areEqual = false;
s.Stop();
}
});
return areEqual;
I would say that the best one depends on what your input will be.
If you will work with huge arrays (like 10000+) I would say Parallel
is the best choice, it only loses when there is a difference on the beginning.
For other cases SequenceEqual
might be the best one, I only tested with int[]
, but I believe it can be fast with complex types as well.
But remember, results will vary accordingly to the input.
这篇关于如何最有效地测试,如果两个数组包含在C#相当于项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!