1

Automation - selenium using C#

We are reading a table which returns value in List<string[]>. We need to compare the values before and after an action performed, which should not affect the table content.

Is there a way to compare both

List<string[]> ExpRequestItemsWithSection  

with

List<string[]> ActRequestItemsWithSection

Till now i was using below code and it works fine. But is there any other way to compare both the collections? Any idea of making this quicker and less resource intensive as i need to process a lot of lists?

bool isRequestsMatch = true;

for (int i = 0; i < ActRequestItemsWithSection.Count; i++)
{
  if (!((ActRequestItemsWithSection[i][0] == ExpRequestItemsWithSection[i][0]) && 
     (ActRequestItemsWithSection[i][1] == ExpRequestItemsWithSection[i][1])))
    isRequestsMatch = false;
}

PFB screenshot from Immediate window

enter image description here

enter image description here

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
KR Akhil
  • 877
  • 3
  • 15
  • 32
  • breaking the loop right after `isRequestsMatch = false;` will eliminate redundant checks – max Dec 30 '19 at 11:39
  • @PavelAnikhouski - I tried solutions mentioned in that link. But i am not able to get desired output. I am trying more regarding the same. – KR Akhil Dec 30 '19 at 11:41
  • @max - Good suggestion thanks. I will make that change. – KR Akhil Dec 30 '19 at 11:42

3 Answers3

3

Well, if order matters, i.e.

 {["A", "B"]} != {["B, A"]}   // A and B swapped within the array

and

 {                   { 
  ["A", "B"],         ["C"],     // [A, B] and [C] arrays are swapped
  ["C"]        !=     ["A, "B"]
 }                   }

Then you can check equality with a help of Linq:

bool equals = (ExpRequestItemsWithSection.Count == ActRequestItemsWithSection.Count) &&
  ExpRequestItemsWithSection
    .Zip(ActRequestItemsWithSection, (left, right) => left.SequenceEqual(right))
    .All(item => item);
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
3

There is a System.Collections.StructuralComparisons.StructuralEqualityComparer, but for some obscure reason it is written in an ugly nongeneric way that makes it hard to use as a generic IEqualityComparer<>.

If you wrap it like this:

class GenericStructuralEqualityComparer<T> : EqualityComparer<T>
  where T : System.Collections.IStructuralEquatable
{
  public override bool Equals(T x, T y)
    => System.Collections.StructuralComparisons.StructuralEqualityComparer.Equals(x, y);

  public override int GetHashCode(T obj)
    => System.Collections.StructuralComparisons.StructuralEqualityComparer.GetHashCode(obj);
}

then you can do SequenceEqauls on the outer (List<>) level:

if (!
  ExpRequestItemsWithSection.SequenceEqual(ActRequestItemsWithSection,
    new GenericStructuralEqualityComparer<string[]>())
  )

Maybe prettier than the .Zip solution?


Addition: If you like .Zip, you can use StructuralEqualityComparer without a wrapping class:

if (
  ExpRequestItemsWithSection.Count != ActRequestItemsWithSection.Count
  ||
  ExpRequestItemsWithSection.Zip(ActRequestItemsWithSection,
    System.Collections.StructuralComparisons.StructuralEqualityComparer.Equals)
  .Contains(false)
  )

This uses the method group System.Collections.StructuralComparisons.StructuralEqualityComparer.Equals whose signature and return type is good enough for a Func<string[], string[], bool> which .Zip takes (tried with C# 7.3 compiler).

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
0

Maybe you are looking for this answer

if (a1.SequenceEqual(a2))
Amit_N
  • 1
  • sorry but it doesn't work. I have added screenshot with your suggestion. It is returning false – KR Akhil Dec 30 '19 at 11:43
  • var list1 = new List(){"a", "b", "c"}; var list2 = new List(){"a", "b", "c"}; Console.WriteLine(list1.SequenceEqual(list2).ToString()); – Amit_N Dec 30 '19 at 13:36