How to compare two List<string[]> in C# [duplicate] - c#

This question already has answers here:
Quickest way to compare two generic lists for differences
(18 answers)
Closed 3 years ago.
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

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);

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).

Maybe you are looking for this answer
if (a1.SequenceEqual(a2))

Related

Elegant way to query a dictionary in C#

I am trying to create an elegant and extensible way of querying a dictionary which maps an enum to a set of strings.
So I have this class SearchFragments that has the dictionary in it. I then want a method wherein consumers of this class can simply ask "HasAny" and, this is the bit where I am struggling, simply pass in some query like expression and get the boolean answer back.
public class SearchFragments
{
private readonly IDictionary<SearchFragmentEnum, IEnumerable<string>> _fragments;
public SearchFragments()
{
_fragments = new Dictionary<SearchFragmentEnum, IEnumerable<string>>();
}
public bool HasAny(IEnumerable<SearchFragmentEnum> of)
{
int has = 0;
_fragments.ForEach(x => of.ForEach(y => has += x.Key == y ? 1 : 0));
return has >= 1;
}
}
The problem with the way this currently is, is that consumers of this class now have to construct an IEnumerable<SearchFragmentEnum> which can be quite messy.
What I am looking for is that the consuming code will be able to write something along the lines of:
searchFragments.HasAny(SearchFragmentEnum.Name, SearchFragmentEnum.PhoneNumber)
But where that argument list can vary in size (without me having to write method overloads in the SearchFragments class for every possible combination (such that if new values are added to the SearchFragmentEnum at a future date I won't have to update the class.
You can use params[]
public bool HasAny(params SearchFragmentEnum[] of)
{ ...
Sidenote: you know that LIN(Q) queries should just query a source and never cause any side-effects? But your query does unnecessarily increment the integer:
_fragments.ForEach(x => of.ForEach(y => has += x.Key == y ? 1 : 0));
Instead use this (which is also more efficient and more readable):
return _fragments.Keys.Intersect(of).Any();
An even more efficient alternative to this is Sergey's idea:
return of?.Any(_fragments.ContainsKey) == true;
For variable sized arguments in c# you use the params keyword:
public int HasAny(params SearchFragmentEnum[] of)
The .Net API usually offers a couple of overloads of this for performance reasons; the parameters passed are copied into a new array. Explicitely providing overloads for the most common cases avoids this.
public int HasAny(SearchfragmentEnum of1)
public int HasAny(SearchFragmentEnum of1, SearchFragmentEnum of2)
etc.
Instead of using params you could also consider marking your enum with the [Flags] attribute. Parameters could than be passed like HasAny(SearchFragmentEnum.Name | SearchFragmentEnum.PhoneNumber. Examples abundant on StackOverflow (e.g. Using a bitmask in C#)
Use the params keyword to allow a varying number of arguments. Further, you can simplify your code by looping over the smaller of array. Also, you are using a dictionary that has O(1) key check, so it is uneccessary to have an inner loop:
public bool HasAny(params SearchFragmentEnum[] of)
{
foreach(var o in of) {
if (this._fragments.ContainsKey(o))
return true;
}
return false;
}
or shorter with LINQ
public bool HasAny(params SearchFragmentEnum[] of) {
return of?.Any(_fragments.ContainsKey) ?? false;
}

Is it possible to return the object with the minimal property in a list? [duplicate]

This question already has answers here:
How to use LINQ to select object with minimum or maximum property value
(20 answers)
Closed 7 years ago.
My solution is
class Test
{
public int X;
}
class Program
{
static void Main(string[] args)
{
var arr = new List<Test>();
var min = arr.Min(x => x.X);
Test a = arr.First(y => y.X == min);
}
}
Can this be done in just one-line (only iterating the list once instead of twice)?
There's a popular extension to linq in "MoreLinq" which provides a "MinBy" method:
https://www.nuget.org/packages/MoreLinq.Source.MoreEnumerable.MinBy/
Using that, your code would become:
Test a = arr.MinBy(item => item.X);
Also see https://www.nuget.org/packages?q=id%3Amorelinq
We routinely use the extensions from MoreLinq in many of our projects - it's definitely worth. (Originally written by Jon Skeet and others, I believe.)
why not just order the sequence by the property you want in ascending order and get the first item?
arr.OrderBy(x => x.X).FirstOrDefault();
I just find this and this is a duplicate question
In the question you want a single iteration, and in response to #dotctor you say that the performance of his solution is worse, thereby saying that performance is important too. Which is more important, performance, or the single iteration?
In this case you can have what you want, but you have to do it without Linq. Loop through the data, and remember the object with the lowest value of X.
var arr = new List<Test>();
Test minimum = null;
foreach (var x in arr) {
if (minimum == null || x.X < minimum.X) {
minimum = x;
}
}
// minimum now contains the object with the lowest value of X.

TryParse dilemma-Dealing with out parameters [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I never liked out and ref parameters.When I see them in action they give me a feeling that something is messy about the design.
I thought that the only exception was the so called TryXXX pattern that returns a boolean as the function result (whether everything was fine or something went wrong) and an out parameter for the real result, until I read this article today and It made me think if there's a better pattern to implement this kind of methods.
I thought that we could either have a function that returns more than one result(or as the article says a tuple)
Tuple<Exception,T> TryParseT(object obj)
or a function that accepts a callback function for success :
void TryParseT(object obj,Action<T> success)
The question is , which one is better from a functional design point of view ?
UPDATE :
To rephrase my question , I want to know which of these two functions more complies with Functional Programming principles and why ?
Essentially the problem is that to follow the functional programming approach you should always provide a return value for an input value. So the returning void route isn't the way to go. You need to return a value that can represent success (and hold the successful result) and failure (and hold no result).
The closest to that is where you have returned a Tuple which includes the exception. However you then don't have the 'infrastructure' to deal with the Tuple reliably once you've got it. So the code scaffolding around it will be repeated.
Take a look at this library language-ext. It deals with improving the out problem for TryParse using its implementation of Option<T>.
string inp = "123";
// Attempts to parse the value, uses 0 if it can't
int value1 = parseInt(inp).IfNone(0);
// Functional alternative to above
// Attempts to parse the value, uses 0 if it can't
int value2 = ifNone(parseInt(inp), 0);
// Attempts to parse the value and then pattern matches the result
int value3 = parseInt(inp).Match(
Some: x => x * 2,
None: () => 0
);
// Functional alternative to above
// Attempts to parse the value and then pattern matches the result
int value4 = match( parseInt(inp),
Some: x => x * 2,
None: () => 0
);
The library also allows you to just check that something is valid:
if( parseInt(inp) )
return 1;
else
return 0;
And allows for comparisons without actually extracting the value:
if( parseInt(inp) == 123 )
return 123;
else
return 0;
As well as logical operations:
var allValid = parseInt(x) && parseInt(y) && parseInt(z);
var someValid = parseInt(x) || parseInt(y) || parseInt(z);
And finally LINQ expressions which can often remove the need for if-then-else or matching:
var res = from x in parseInt(inp1)
from y in parseInt(inp2)
from z in parseInt(inp3)
select x + y + z;
It also has TryGetValue extensions for IDictionary, IReadOnlyDictionary, IImmutableDictionary and IImmutableSet that instead return Option<T> and can be used as above.
The most elegant method is
int Parse(string value)
The Tryxxxx methods only exist for an implementation detail named performance. If you are seeking elegance you can use the Parse method and handle any errors by failing fast.
You can instead return a tuple but this will cost an additional allocation on the heap since Tuple is a reference type.
A better solution in terms of performance (if you care) would be aKeyValuePair. But it hides (like tuple) the semantics behind generic data types which is not optimal for code clarity. A better way to signal failure than by defining some convention that the first bool of the tuple contains the failure state is by defining your own data type.
struct ParseResult<T>
{
public bool Success { get; private set; }
public T Value { get; private set; }
public ParseResult(T value, bool success):this()
{
Value = value;
Success = success;
}
}
class Program
{
static ParseResult<int> TryParse(string s)
{
int lret = 0;
if (int.TryParse(s, out lret))
{
return new ParseResult<int>(lret, true);
}
else
{
return new ParseResult<int>(lret, false);
}
}
static void Main(string[] args)
{
string test = "1";
var lret = TryParse(test);
if( lret.Success )
{
Console.WriteLine("{0}", lret.Value);
}
}
}
That approach is still quite efficient and spares you the out parameters at the cost of the allocation of a cheap container object.

Compare multiple values in one condition [duplicate]

This question already has answers here:
Equality comparison between multiple variables
(14 answers)
Closed 7 years ago.
Int32 int1, int2, int3 = 123;
Given the above variables, how can I test that all of my variables have the value 123 without creating a collection to perform some Any or something on?
What I've Tried
if(int1 == int2 == int3 == 123)
{
// Fantastic code here
}
EDIT
I must apologise, I haven't been clear enough in my question. I'm fully aware of the && operator, I was asking with regard to 'elegance', i.e. how can I avoid repeating the value I want to compare against.
In the same way I have assigned all 3 integer variables the same value in one hit, I'd like to now make the comparison. It's looking as though there is no way of doing this, so far. I think I'm asking the impossible, I'll have to stick to the basic syntax and keep it simple.
You can create an usefull extension function:
public static bool EqualsAll<T>(this T val, params T[] values)
{
return values.All(v => v.Equals(val));
}
call it like:
bool res = 123.EqualsAll(int1,int2,int3);
You could try something like this, using the logical and operator:
if(int1 == 123 &&
int2 == 123 &&
int3 == 123)
{
}
if(int1 == 123 && int2 == 123 && int3 == 123) { // Code }
What your trying to achieve isn't possible the way you do it.
You have to separate it with &.
if(int1 == something && int2 == something && int3 == 123)
{
// Fantastic code here
}
This is how you should do it using && operator. You can check multiple conditions using this.
UPDATE :
As far as checking multiple values at one go is concerned, you can try making an array out those values and just fire a simple LINQ statement like this to check all of them for a particular value :
if (new[] { int1, int2, int3 }.All(x => x == 1))
Dont know if this fits into your requirement, just a suggestion though.

Using Linq Except not Working as I Thought

List1 contains items { A, B } and List2 contains items { A, B, C }.
What I need is to be returned { C } when I use Except Linq extension. Instead I get returned { A, B } and if I flip the lists around in my expression the result is { A, B, C }.
Am I misunderstanding the point of Except? Is there another extension I am not seeing to use?
I have looked through and tried a number of different posts on this matter with no success thus far.
var except = List1.Except(List2); //This is the line I have thus far
EDIT: Yes I was comparing simple objects. I have never used IEqualityComparer, it was interesting to learn about.
Thanks all for the help. The problem was not implementing the comparer. The linked blog post and example below where helpful.
If you are storing reference types in your list, you have to make sure there is a way to compare the objects for equality. Otherwise they will be checked by comparing if they refer to same address.
You can implement IEqualityComparer<T> and send it as a parameter to Except() function. Here's a blog post you may find helpful.
edit: the original blog post link was broken and has been replaced above
So just for completeness...
// Except gives you the items in the first set but not the second
var InList1ButNotList2 = List1.Except(List2);
var InList2ButNotList1 = List2.Except(List1);
// Intersect gives you the items that are common to both lists
var InBothLists = List1.Intersect(List2);
Edit: Since your lists contain objects you need to pass in an IEqualityComparer for your class... Here is what your except will look like with a sample IEqualityComparer based on made up objects... :)
// Except gives you the items in the first set but not the second
var equalityComparer = new MyClassEqualityComparer();
var InList1ButNotList2 = List1.Except(List2, equalityComparer);
var InList2ButNotList1 = List2.Except(List1, equalityComparer);
// Intersect gives you the items that are common to both lists
var InBothLists = List1.Intersect(List2);
public class MyClass
{
public int i;
public int j;
}
class MyClassEqualityComparer : IEqualityComparer<MyClass>
{
public bool Equals(MyClass x, MyClass y)
{
return x.i == y.i &&
x.j == y.j;
}
public int GetHashCode(MyClass obj)
{
unchecked
{
if (obj == null)
return 0;
int hashCode = obj.i.GetHashCode();
hashCode = (hashCode * 397) ^ obj.i.GetHashCode();
return hashCode;
}
}
}
You simply confused the order of arguments. I can see where this confusion arose, because the official documentation isn't as helpful as it could be:
Produces the set difference of two sequences by using the default equality comparer to compare values.
Unless you're versed in set theory, it may not be clear what a set difference actually is—it's not simply what's different between the sets. In reality, Except returns the list of elements in the first set that are not in the second set.
Try this:
var except = List2.Except(List1); // { C }
Writing a custom comparer does seem to solve the problem, but I think https://stackoverflow.com/a/12988312/10042740 is a much more simple and elegant solution.
It overwrites the GetHashCode() and Equals() methods in your object defining class, then the default comparer does its magic without extra code cluttering up the place.
Just for Ref:
I wanted to compare USB Drives connected and available to the system.
So this is the class which implements interface IEqualityComparer
public class DriveInfoEqualityComparer : IEqualityComparer<DriveInfo>
{
public bool Equals(DriveInfo x, DriveInfo y)
{
if (object.ReferenceEquals(x, y))
return true;
if (x == null || y == null)
return false;
// compare with Drive Level
return x.VolumeLabel.Equals(y.VolumeLabel);
}
public int GetHashCode(DriveInfo obj)
{
return obj.VolumeLabel.GetHashCode();
}
}
and you can use it like this
var newDeviceLst = DriveInfo.GetDrives()
.ToList()
.Except(inMemoryDrives, new DriveInfoEqualityComparer())
.ToList();

Categories

Resources