Condition if for Nunit assert - c#

I need to compare two Lists by NUnit's Assert.AreEqual. If this statement is false (lists not the same) - then I need find elements in lists which not the same.
How I can use If statement for know- Assert return true or false?

It seems that nunit CollectionAssert.AreEquivalent is exactly what you were looking for.
This method compare between the collections.
If a mismatch was found then the method will throw exception with the difference.

Here's a possible solution.
[Test]
public void TestMethod1()
{
List<int> a = new List<int>();
List<int> b = new List<int>();
//Fake data
a.Add(1);
b.Add(2);
b.Add(2);
Assert.IsTrue(AreEquals(a,b), GetDifferentElements(a,b));
}
private string GetDifferentElements(List<int> a, List<int> b)
{
if (AreEquals(a, b))
{
return string.Empty;
}
if (a.Count != b.Count)
{
return "The two lists have a different length";
}
StringBuilder s = new StringBuilder();
for (int i = 0; i < a.Count; i++)
{
if (a[i] != b[i])
{
s.Append(i.ToString() + " ");
}
}
return string.Format("Elements at indexes {0} are different", s.ToString());
}
private bool AreEquals(List<int> a, List<int> b)
{
if (a.Count != b.Count)
{
return false;
}
for (int i = 0; i < a.Count; i++)
{
if (a[i] != b[i])
{
return false;
}
}
return true;
}
UPDATE
Of course I was unaware of the CollectionAssert.AreEquivalent method provided in the accepted answer. That's a better solution of course!

Related

Merging two lists which are already sorted in c#

So i have two sorted lists with deliverable's and I want to Merge them. I never did this operation before and i can not really make it work. You can see method below that i wrote. I can not figure out while statement because it fires exception all the time. I dont know what to do...
public void MergeLists(List<Deliverable> a, List<Deliverable> b)
{
int index1 = 0;
int index2 = 0;
while (a.Count() >= index1 || b.Count() >= index2)
{
if (a[index1].ID> b[index2].ID)
{
FinalDeliverables.Add(a[index1]);
index1++;
}
else if (a[index1].ID < b[index2].ID)
{
FinalDeliverables.Add(a[index2]);
index2++;
}
else if (a[index1].ID == b[index2].ID)
{
FinalDeliverables.Add(a[index1]);
FinalDeliverables.Add(a[index2]);
index1++;
index2++;
}
}
}
I believe that the exceptions you are getting are coming from null pointers. This would occur if, for example, you already reached the end of one of the lists, yet your while loop is still trying to compare values. One workaround to this is to simply add a check before the if statements to see if one (or both) of the ends of the lists have been reached. If so, then simply add the remainder of the items from the other list.
public void MergeLists(List<Deliverable> a, List<Deliverable> b)
{
int index1 = 0;
int index2 = 0;
while (true)
{
// if the end of the 'a' list has been reached, then add
// everything from the 'b' list and break from the loop
if (index1 >= a.Count()) {
for (int i=index2; i < b.Count(); ++i) {
FinalDeliverables.Add(b[i]);
}
break;
}
// if the end of the 'b' list has been reached, then add
// everything from the 'a' list and break from the loop
if (index2 >= b.Count()) {
for (int i=index1; i < a.Count(); ++i) {
FinalDeliverables.Add(a[i]);
}
break;
}
if (a[index1].ID > b[index2].ID)
{
FinalDeliverables.Add(a[index1]);
index1++;
}
else if (a[index1].ID < b[index2].ID)
{
FinalDeliverables.Add(a[index2]);
index2++;
}
else if (a[index1].ID == b[index2].ID)
{
FinalDeliverables.Add(a[index1]);
FinalDeliverables.Add(a[index2]);
index1++;
index2++;
}
}
}
Note that a side effect of this refactor is that your original while loop no longer has to check boundaries. Instead, the loop will be terminated when one of the lists has been exhausted.
Also note that this solution assumes that your input lists are sorted in descending order.
You can use the LINQ Extension methods for this purpose, The Method signature for MergeLists will be like the following:
public void MergeLists(List<Deliverable> a, List<Deliverable> b)
{
var finalList = a.Concat(b);
List<Deliverable> FinalSortedList = finalList.OrderBy(x => x.ID).ToList();
}
Or else you can modify your own method as like the following: Before that Let me assume the following, The Count of elements in the Input list a will always be Greater than that of b. SO what you need to do is Check the count of elements before calling the method as well. So the call will be like the following:
if(a.Count>b.Count)
MergeLists(a,b);
else
MergeLists(b,a);
You mentioned that the two inputs ware sorted, Let me assume those lists are sorted in ascending order. Now consider the following code:
public void MergeLists(List<Deliverable> a, List<Deliverable> b)
{
int largeArrayCount = a.Count;
int currentBIndex = 0;
List<Deliverable> FinalResult = new List<Deliverable>();
for (int i = 0; i < largeArrayCount; i++)
{
if (i < b.Count)
{
if (a[i].ID >= b[i].ID)
{
// Add All elements of B Which is smaller than current element of A
while (a[i].ID <= b[currentBIndex].ID)
{
FinalResult.Add(b[currentBIndex++]);
}
}
else
{
FinalResult.Add(a[i]);
}
}
else
{
// No more elements in b so no need for checking
FinalResult.Add(a[i]);
}
}
}

Two Arrays have same values but do not returns equal

I want to compare two arrays and if all the values are the same i will do some stuff. I write a function like this to check is there any different value. If so return false.
bool Deneme ()
{
for (int i = 0; i < correctOnes.Length; i++) {
if(correctOnes[i] != cubeRotation[i].rotation.eulerAngles)
{
return false;
}
}
return true;
}
When I call the Deneme function it always return false. However, I check the array values in the console they are all same. Any ideas what is going on ?
Checking the console like that
for (int i = 0; i < correctOnes.Length; i++) {
Debug.Log ("Corrects: " + correctOnes[i]);
Debug.Log ("Cubes: " + cubeRotation[i].rotation.eulerAngles);
}
Console Photo:
The most likely reason for this is that eulerAngles is double, which means that it should not be compared with operator ==. Two numbers may look the same when printed, but they would compare as non-equal.
The trick here is to compare using Math.Abs(a-b) < 1E-8 method:
if(Math.Abs(correctOnes[i]-cubeRotation[i].rotation.eulerAngles) < 1E-8) {
...
}
Above, 1E-8 is a small number that represents the tolerance for comparing doubles for equality.
You can have a try with
bool Deneme ()
{
for (int i = 0; i < correctOnes.Length; i++) {
if (!Mathf.Approximately (correctOnes[i].magnitude, cubeRotation[i].rotation.eulerAngles.magnitude))
{
return false;
}
}
return true;
}
I posted the test scaffolding for completeness, but the linq query at line #35 should get you your pass/fail results.
class Ans34467714
{
List<double> correctOnes = new List<double>() { 22.7, 22.6, 44.5, 44.5, 44.5};
List<rotation> cubeRotation = new List<rotation>() { new rotation() { eulerAngles = 22.3 }, new rotation() { eulerAngles = 22.6 }, new rotation() { eulerAngles = 44.5 }, new rotation() { eulerAngles = 44.5 }, new rotation() { eulerAngles = 44.5 } };
public Ans34467714()
{
}
internal bool Execute(string[] args)
{
bool retValue = false;
if (Deneme())
{
Console.WriteLine("Pass");
}
else
{
Console.WriteLine("Fail");
}
return retValue;
}
internal bool Deneme()
{
return correctOnes.Where((var, index) => cubeRotation[index].eulerAngles == var).Count() == correctOnes.Count;
}
}
class rotation
{
public double eulerAngles {get; set;}
public rotation()
{
}
}

Checking equality for two byte arrays

I am checking the equality of two byte arrays, and I wanted some help because what I have returns false even though the arrays should be equal.
Within my debug I could see both of a1 and b1 are equal, but it is not going inside the while loop to increment i.
public bool Equality(byte[] a1, byte[] b1)
{
int i;
bool bEqual;
if (a1.Length == b1.Length)
{
i = 0;
while ((i < a1.Length) && (a1[i]==b1[i]))
{
i++;
}
if (i == a1.Length)
{
bEqual = true;
}
}
return bEqual;
}
This always returns false: (a1[i]==b1[i]).
You need to add a return value somewhere. This should work:
public bool Equality(byte[] a1, byte[] b1)
{
int i;
if (a1.Length == b1.Length)
{
i = 0;
while (i < a1.Length && (a1[i]==b1[i])) //Earlier it was a1[i]!=b1[i]
{
i++;
}
if (i == a1.Length)
{
return true;
}
}
return false;
}
But this is much simpler:
return a1.SequenceEqual(b1);
Alternatively, you could use IStructuralEquatable from .NET 4:
return ((IStructuralEquatable)a1).Equals(b1, StructuralComparisons.StructuralEqualityComparer)
If performance is a concern, I'd recommend rewriting your code to use the Binary class, which is specifically optimized for this kind of use case:
public bool Equality(Binary a1, Binary b1)
{
return a1.Equals(b1);
}
A quick benchmark on my machine gives the following stats:
Method Min Max Avg
binary equal: 0.868 3.076 0.933 (best)
for loop: 2.636 10.004 3.065
sequence equal: 8.940 30.124 10.258
structure equal: 155.644 381.052 170.693
Download this LINQPad file to run the benchmark yourself.
To check equality you can just write:
var areEqual = a1.SequenceEqual(b1);
I'd recommend some short-circuiting to make things a bit simpler, and use of object.ReferenceEquals to short-circuit for cases when the arrays are the same reference (a1 = b1):
public bool Equality(byte[] a1, byte[] b1)
{
// If not same length, done
if (a1.Length != b1.Length)
{
return false;
}
// If they are the same object, done
if (object.ReferenceEquals(a1,b1))
{
return true;
}
// Loop all values and compare
for (int i = 0; i < a1.Length; i++)
{
if (a1[i] != b1[i])
{
return false;
}
}
// If we got here, equal
return true;
}
This should work:
public bool Equality(byte[] a1, byte[] b1)
{
if(a1 == null || b1 == null)
return false;
int length = a1.Length;
if(b1.Length != length)
return false;
while(length >0) {
length--;
if(a1[length] != b1[length])
return false;
}
return true;
}
You should add some return statements:
public bool Equality(byte[] a1, byte[] b1)
{
int i = 0;
if (a1.Length == b1.Length)
{
while ((i < a1.Length) && (a1[i]==b1[i]))
{
i++;
}
}
return i == a1.Length;
}
Or, better yet
public bool Equality(byte[] a1, byte[] b1)
{
if(a1.Length != b1.Length)
{
return false;
}
for (int i = 0; i < a1.Length; i++)
{
if (a1[i] != b1[i])
{
return false;
}
}
return true;
}

Incrementing an IEnumerator/IEnumerable while using yield

I am trying to yield iterate through a collection and if the collection is empty then call an increment method that will get the next set of results. When the increment says there are no more results then the yield with break;
I can not use (i think) a standard IEnumerator with MoveNext() etc as the increment method returns two different types of data.
I have tried an example below but it stops after one itteration. I am hoping there is a much easier way to do this (or at least is possible just I have a bug).
static void Main(string[] args)
{
var query = new Query();
foreach(var s in query.Q1())
{
Console.WriteLine(s);
}
foreach (var s in query.Q2())
{
Console.WriteLine(s);
}
Console.ReadLine();
}
public class Query
{
int i = 0;
bool complete;
List<string> q1 = new List<string>();
List<string> q2 = new List<string>();
public IEnumerable<string> Q1()
{
if (complete)
{
yield break;
}
if (!q1.Any() && !complete)
{
Increment();
}
if (q1.Any())
{
foreach (var s in q1)
{
yield return s;
}
}
}
public IEnumerable<string> Q2()
{
if (complete)
{
yield break;
}
if (!q2.Any() && !complete)
{
Increment();
}
if (q2.Any())
{
foreach (var s in q2)
{
yield return s;
}
}
}
void Increment()
{
if (i < 10)
{
// simulate getting two types of data back (parent and two children) from datasource
q1.Add((1 * (i + 1)).ToString());
q2.Add("A: " + (1 * (i + 1)).ToString());
q2.Add("B: " + (1 * (i + 1)).ToString());
i++;
}
else
{
complete = true;
}
}
}
result:
1
A: 1
B: 1
Any ideas on a better way of doing this or where I am going wrong?
EDIT
Here is my rough and ready fix:
public IEnumerable<string> Q1()
{
var index = 0;
if (!complete)
{
while (!complete)
{
var count = q1.Count();
if (index + 1 == count)
{
for (var x = index; index < count; index++)
{
yield return q1[index];
}
}
else
{
Increment();
}
}
}
else
{
foreach (var s in q1)
{
yield return s;
}
}
}
You are adding elements only to q2 list. Thus when you call Q1 iterator, you are exiting it after checking
if (q1.Any())
When you calling Q2 iterator, you exit it after
if (q2.Any())
{
foreach (var s in q2)
{
yield return s;
}
}
This foreach loop is executed only once and it returns only three items which where added to q2 during single Increment call in Q1 iterator.
It's not very clear what you want to achieve, but here is the way you can use loop for generating return values of iterator
public IEnumerable<string> Q2()
{
for (int i = 1; i <= 10; i++) // start from 1
{
yield return i.ToString(); // do not multiply by 1
yield return "A: " + i; // .ToString() is not necessary
yield return "B: " + i;
}
}

N-way intersection of sorted enumerables

Given n enumerables of the same type that return distinct elements in ascending order, for example:
IEnumerable<char> s1 = "adhjlstxyz";
IEnumerable<char> s2 = "bdeijmnpsz";
IEnumerable<char> s3 = "dejlnopsvw";
I want to efficiently find all values that are elements of all enumerables:
IEnumerable<char> sx = Intersect(new[] { s1, s2, s3 });
Debug.Assert(sx.SequenceEqual("djs"));
"Efficiently" here means that
the input enumerables should each be enumerated only once,
the elements of the input enumerables should be retrieved only when needed, and
the algorithm should not recursively enumerate its own output.
I need some hints how to approach a solution.
Here is my (naive) attempt so far:
static IEnumerable<T> Intersect<T>(IEnumerable<T>[] enums)
{
return enums[0].Intersect(
enums.Length == 2 ? enums[1] : Intersect(enums.Skip(1).ToArray()));
}
Enumerable.Intersect collects the first enumerable into a HashSet, then enumerates the second enumerable and yields all matching elements.
Intersect then recursively intersects the result with the next enumerable.
This obviously isn't very efficient (it doesn't meet the constraints). And it doesn't exploit the fact that the elements are sorted at all.
Here is my attempt to intersect two enumerables. Maybe it can be generalized for n enumerables?
static IEnumerable<T> Intersect<T>(IEnumerable<T> first, IEnumerable<T> second)
{
using (var left = first.GetEnumerator())
using (var right = second.GetEnumerator())
{
var leftHasNext = left.MoveNext();
var rightHasNext = right.MoveNext();
var comparer = Comparer<T>.Default;
while (leftHasNext && rightHasNext)
{
switch (Math.Sign(comparer.Compare(left.Current, right.Current)))
{
case -1:
leftHasNext = left.MoveNext();
break;
case 0:
yield return left.Current;
leftHasNext = left.MoveNext();
rightHasNext = right.MoveNext();
break;
case 1:
rightHasNext = right.MoveNext();
break;
}
}
}
}
OK; more complex answer:
public static IEnumerable<T> Intersect<T>(params IEnumerable<T>[] enums) {
return Intersect<T>(null, enums);
}
public static IEnumerable<T> Intersect<T>(IComparer<T> comparer, params IEnumerable<T>[] enums) {
if(enums == null) throw new ArgumentNullException("enums");
if(enums.Length == 0) return Enumerable.Empty<T>();
if(enums.Length == 1) return enums[0];
if(comparer == null) comparer = Comparer<T>.Default;
return IntersectImpl(comparer, enums);
}
public static IEnumerable<T> IntersectImpl<T>(IComparer<T> comparer, IEnumerable<T>[] enums) {
IEnumerator<T>[] iters = new IEnumerator<T>[enums.Length];
try {
// create iterators and move as far as the first item
for (int i = 0; i < enums.Length; i++) {
if(!(iters[i] = enums[i].GetEnumerator()).MoveNext()) {
yield break; // no data for one of the iterators
}
}
bool first = true;
T lastValue = default(T);
do { // get the next item from the first sequence
T value = iters[0].Current;
if (!first && comparer.Compare(value, lastValue) == 0) continue; // dup in first source
bool allTrue = true;
for (int i = 1; i < iters.Length; i++) {
var iter = iters[i];
// if any sequence isn't there yet, progress it; if any sequence
// ends, we're all done
while (comparer.Compare(iter.Current, value) < 0) {
if (!iter.MoveNext()) goto alldone; // nasty, but
}
// if any sequence is now **past** value, then short-circuit
if (comparer.Compare(iter.Current, value) > 0) {
allTrue = false;
break;
}
}
// so all sequences have this value
if (allTrue) yield return value;
first = false;
lastValue = value;
} while (iters[0].MoveNext());
alldone:
;
} finally { // clean up all iterators
for (int i = 0; i < iters.Length; i++) {
if (iters[i] != null) {
try { iters[i].Dispose(); }
catch { }
}
}
}
}
You can use LINQ:
public static IEnumerable<T> Intersect<T>(IEnumerable<IEnumerable<T>> enums) {
using (var iter = enums.GetEnumerator()) {
IEnumerable<T> result;
if (iter.MoveNext()) {
result = iter.Current;
while (iter.MoveNext()) {
result = result.Intersect(iter.Current);
}
} else {
result = Enumerable.Empty<T>();
}
return result;
}
}
This would be simple, although it does build the hash-set multiple times; advancing all n at once (to take advantage of sorted) would be hard, but you could also build a single hash-set and remove missing things?

Categories

Resources