I am trying to check if list of arrays contains array with factors in reverse order and if not, add them:
var faclist = new List<int[]>();
var factors = new int[2] {i, j};
if (!faclist.Contains(factors.Reverse()))
{
faclist.Add(factors);
}
However this code always not true even there are arrays with reversed factors.
The .Contains works on the .Equals method. By default, the .Equals method returns only true, if the two instances (references) are the same.
A possible way to solve this - if the number of factors are fixed - is using a Tuple<int,int>. You can define the Reverse method on a `Tuple class with:
public static class Foo {
public static Tuple<T2,T1> Reverse<T1,T2> (this Tuple<T1,T2> tuple) {
return new Tuple<T2,T1>(tuple.Item2,tuple.Item1);
}
}
And then call it simply with:
Tuple<int,int> t = new Tuple<int,int>(3,5);
Tuple<int,int> t2 = t.Reverse();
If not, you could define a wrapper class, that performs the equality check as described here.
Or another alternative, is to provide an equality checker yourself in the .Contains method as described by #xanatos answer.
Demo:
$ csharp
Mono C# Shell, type "help;" for help
Enter statements below.
csharp> var t1 = new Tuple<int,int>(3,2);
csharp> var t2 = new Tuple<int,int>(3,2);
csharp> t1.Equals(t2);
true
csharp> int[] t1 = new int[] {3,2};
csharp> int[] t2 = new int[] {3,2};
csharp> t1.Equals(t2);
false
As written by CommuSoft, because arrays don't implement comparison in the way you think (they do only reference comparison)
Another solution is to implement an equality comparer:
public class IntArrayComparison : IEqualityComparer<int[]> {
public bool Equals(int[] x, int[] y) {
if (x == null) {
return y == null;
}
if (y == null) {
return false;
}
return x.SequenceEqual(y);
}
public int GetHashCode(int[] obj) {
throw new NotImplementedException();
}
}
if (!faclist.Contains(factors.Reverse().ToArray(), new IntArrayComparison())) {
And then use it in the Contains method. (note that I have to change the result of Reverse() back to an array, because Reverse() returns an IEnumerable<T>)
Related
Let's say I've an extension method like this one
public static IEnumerable<int> DoThings(this int n)
{
var mList = new List<int> { 2, 3, 4, 5 };
var result = new List<int>();
foreach(var m in mList)
result.Add(n * m);
return result;
}
Is there a way to "genericize" so i can use it also on long and get a IEnumerable<long> as a result?
if I go simply with public static IEnumerable<T> DoThings<T>(this T n) its hard to do the math without ending in Cast<> and Convert vortex
There´s no generic constraint that would fit for only Int32 (which is int) and Int64 (which is long), while not fitting for any other numeric type.
However you can just create two extension-methods where one references the other:
public static IEnumerable<int> DoThings(this int n)
{
return DoThings((long) n).Cast<int>();
}
public static IEnumerable<long> DoThings(this long n)
{
var mList = new List<int> { 2, 3, 4, 5 };
var result = new List<long>();
foreach(var m in mList)
result.Add(n * m);
return result;
}
Be aware that the result may also exceed the max-number for Int32, in which case you´d get an InvalidCastException when calling the int-version.
However as an int can implicitely be cast to long anyway, I can't see why you even want two methods. Stay with that for long and forget about the int-version altogether.
Maybe overriding isn't the correct term here.
I want to extend some of the System.Math class functions to work on double arrays.
What I'm currently doing is:
public double[] Sin(double[] d)
{
double[] result = new double[d.Length];
for(int i=0;i<result.Length;i++)
result[i] = Math.Sin(d[i]);
}
For many functions in a Math (about 20) just replacing Sin by Cos,Round,...
Is there a way to make this more elegant?
Please note that I'm building something to allow the user to evaluate expressions in runtime.
The user needs to be able to write "Cos(d)" for d double array and for all the functions, so solutions from the input side aren't really an option.
Thanks all
Not really, but you can shorten it with Array.ConvertAll:
double[] result = Array.ConvertAll(d, Math.Sin);
If the function name is in a string, you might be able to use a dictionary:
var dict = new Dictionary<string, Func<double[], double[]>> {
{ "Sin", a => Array.ConvertAll(a, Math.Sin) },
{ "Cos", a => Array.ConvertAll(a, Math.Cos) }
};
double[] d = { 1, 2 };
double[] result = dict["Sin"](d); // { 0.8414709848078965, 0.90929742682568171 }
You can create more generic method to work with the arrays. Something like this
internal static void Transform(double[] values, Func<double, double> transformation)
{
for(int i = 0; i < values.Length; i++)
values[i] = transformation[values[i]];
}
Now you can use more concrete methods like
internal static void Sin(doube[] values)
{
return Transform(values, Math.Sin);
}
Or
internal static void Cos(doube[] values)
{
return Transform(values, Math.Cos);
}
the the usage will be like this
var result = Sin(values)
You could use Extension methods:
public static class MathExtensions
{
public static double[] Sin(this double[] input)
{
return input.Select(Math.Sin).ToArray();
}
}
And then the call would be:
var f = d.Sin();
Note: This doesn't get the syntax you wanted, nor does it solve the issue of having to write one of these for each of the corresponding Math methods but I'll post it here as an answer to how to extend existing methods more elegantly.
Sorry for the vague title but I'll try and describe what my problem as best as I can below.
Basically I have 5 string arrays that all hold data relevant to the same index in the other arrays. For example, element 5 in array 1 corresponds to element 5 in arrays 2, 3, 4 and 5.
What I have done is used the Quicksort algorthim to sort array 1 into alphabetical order. The problem is that when the array is sorted, no longer do elements in the other arrays correspond since the other arrays haven't been sorted.
What I need is some way to swap the same elements around in the other 4 arrays as has been down to array 1. For example, if element 2 in array 1 is swapped to element 55, then element 2 in the other 4 arrays need to be swapped to element 55 in their array and vice versa.
The end goal is to display all the data in a specific element across all 5 arrays.
Below I have added the quicksort algorithm I'm using and added 3 example arrays that need sorting:
string[] array1 = {"z","y","x","a"};
string[] array2 = {"26","25","24","1"};
string[] array3 = { "black","yellow","white","red" };
// The first 2 arrays should clarify my point further.
// I use Quicksort to sort array 1
public static void QuicksortSTRING(IComparable[] elements, int left, int right)
{
int i = left, j = right;
IComparable pivot = elements[(left + right) / 2];
while (i <= j)
{
while (elements[i].CompareTo(pivot) < 0)
{
i++;
}
while (elements[j].CompareTo(pivot) > 0)
{
j--;
}
if (i <= j)
{
// Swap
IComparable tmp = elements[i];
elements[i] = elements[j];
elements[j] = tmp;
i++;
j--;
}
}
// Recursive calls
if (left < j)
{
QuicksortSTRING(elements, left, j);
}
if (i < right)
{
QuicksortSTRING(elements, i, right);
}
}
If you need any other info just ask.
It’s better to put the three related strings into a single object:
sealed class RelatedInformation // or struct, you decide
{
public string First;
public string Second;
public string Third;
}
and then sort a list of those objects:
var myList = new List<RelatedInformation>();
// insert code that populates the list here
myList.Sort((a, b) => a.First.CompareTo(b.First));
or, if it needs to be an array:
var myArray = /* obtain the RelatedInformation[] here */;
Array.Sort(myList, (a, b) => a.First.CompareTo(b.First));
Additionally, there is no need for you to implement Quicksort yourself (unless this is homework? :)). You can just use Array.Sort or List<T>.Sort with a lambda expression that specifies your sort criterion.
You don’t even need to implement the IComparable<T> interface if you use the above code. However, if the RelatedInformation class (or struct) is used in many places that have something to do with their ordering, it may be wise to implement it anyway; then you can ditch the lambdas:
sealed class RelatedInformation : IComparable<RelatedInformation>
{
public string First;
public string Second;
public string Third;
public int CompareTo(RelatedInformation other)
{
return First.CompareTo(other.First);
}
}
// ...
var myList = new List<RelatedInformation>();
// insert code that populates the list
myList.Sort();
However, since you explicitly asked about the three-array situation, here is a solution that will work under that constraint. Instead of sorting any one of the arrays, the idea is to sort a list of the indexes. I’m going to use LINQ for this because it’s pretty succint and readable:
var sortedIndexes = Enumerable.Range(0, array1.Length)
.OrderBy(i => array1[i])
.ToArray();
var sortedArray1 = sortedIndexes.Select(i => array1[i]).ToArray();
var sortedArray2 = sortedIndexes.Select(i => array2[i]).ToArray();
var sortedArray3 = sortedIndexes.Select(i => array3[i]).ToArray();
Pretty short, huh? Of course, in the call to OrderBy, you can specify any other array to sort by.
Do be aware though that this code will throw an exception if any of the arrays is shorter than the first one, and it will silently discard items if any of the arrays is longer than the first one. One major benefit of the list-of-objects solution is that you do not need to worry about that.
As an added piece of information, the OrderBy from LINQ is a stable sort; this means that items where array1 has the same string stay in the same order. Array.Sort and List<T>.Sort do not have a stable sort.
You can even use this method to sort by multiple criteria; for example, let’s say you want to sort by the strings in array1, but whenever array1 has the same string for some items, you want those items to be sorted by whatever is in array2. You can do that using ThenBy:
var sortedIndexes = Enumerable.Range(0, array1.Length)
.OrderBy(i => array1[i])
.ThenBy(i => array2[i])
.ToArray();
You've got these three items of information to sort. Try creating a class to hold them. It can be an inner class inside one of your program classes if you want.
struct MyThing :IComparable {
char a;
int b;
string c;
}
Then make a List<MyThing>. Then populate it with your data.
You'll need to implement the IComparable interface (requiring your own CompareTo method) for your class, so it knows to sort on a, or whatever you want sorted.
Then use the built in List.Sort() function or your own quicksort method.
I think it would make more sense if you stored all your related information together in one array, e.g.:
var array = new[] { Tuple.Create("z", "26", "black"),
Tuple.Create("y", "25", "yellow"),
Tuple.Create("x", "24", "white"),
Tuple.Create("a", "1", "red") };
Then you can sort your array by any key you like and preserving other elements at corresponding positions.
You could approach this by putting all your related strings into a single class, rather than keeping them all in separate arrays.
For example:
public class Demo
{
public string Key;
public string S1;
public string S2;
public override string ToString()
{
return string.Format("Key: {0}, S1: {1}, S2: {2}", Key, S1, S2);
}
}
Then when you want to sort that, you need a way to determine which property or properties to use when comparing elements. There are several ways to do this; one is to make your type implement IComparable<T>.
However there is another more flexible approach. You can supply to your sort method an IComparer<T> object that it can use to compare elements.
Using this, you can "pick out" the member of a class that you want to use when comparing.
Here's a full example:
using System;
using System.Collections.Generic;
namespace Demo
{
public class Demo
{
public string Key;
public string S1;
public string S2;
public override string ToString()
{
return string.Format("Key: {0}, S1: {1}, S2: {2}", Key, S1, S2);
}
}
static class Program
{
static void Main()
{
var list = new List<Demo>
{
new Demo {Key = "Z", S1 = "Z1", S2 = "Z2"},
new Demo {Key = "Y", S1 = "Y1", S2 = "Y2"},
new Demo {Key = "X", S1 = "X1", S2 = "X2"},
new Demo {Key = "W", S1 = "W1", S2 = "W2"},
new Demo {Key = "V", S1 = "V1", S2 = "V2"}
};
// Rather than write your own IComparer<Demo> implementation, you can
// leverage a built-in .Net implementation by using
// Comparer<Demo>.Create() as follows:
var keyComparer = Comparer<Demo>.Create((x, y) => string.Compare(x.Key, y.Key, StringComparison.Ordinal));
QuicksortSTRING(list, 0, list.Count-1, keyComparer);
Console.WriteLine(string.Join("\n", list));
}
public static void QuicksortSTRING<T>(IList<T> elements, int left, int right, IComparer<T> comparer)
{
int i = left, j = right;
var pivot = elements[(left + right)/2];
while (i <= j)
{
while (comparer.Compare(elements[i], pivot) < 0)
{
i++;
}
while (comparer.Compare(elements[j], pivot) > 0)
{
j--;
}
if (i <= j)
{
// Swap
T tmp = elements[i];
elements[i] = elements[j];
elements[j] = tmp;
i++;
j--;
}
}
// Recursive calls
if (left < j)
{
QuicksortSTRING(elements, left, j, comparer);
}
if (i < right)
{
QuicksortSTRING(elements, i, right, comparer);
}
}
}
}
I wish to create the following test in NUnit for the following scenario: we wish to test the a new calculation method being created yields results similar to that of an old system. An acceptable difference (or rather a redefinition of equality) between all values has been defined as
abs(old_val - new_val) < 0.0001
I know that I can loop through every value from the new list and compare to values from the old list and test the above condition.
How would achieve this using Nunit's CollectionAssert.AreEqual method (or some CollectionAssert method)?
The current answers are outdated. Since NUnit 2.5, there is an overload of CollectionAssert.AreEqual that takes a System.Collections.IComparer.
Here is a minimal implementation:
public class Comparer : System.Collections.IComparer
{
private readonly double _epsilon;
public Comparer(double epsilon)
{
_epsilon = epsilon;
}
public int Compare(object x, object y)
{
var a = (double)x;
var b = (double)y;
double delta = System.Math.Abs(a - b);
if (delta < _epsilon)
{
return 0;
}
return a.CompareTo(b);
}
}
[NUnit.Framework.Test]
public void MyTest()
{
var a = ...
var b = ...
NUnit.Framework.CollectionAssert.AreEqual(a, b, new Comparer(0.0001));
}
Well there is method from the NUnit Framework that allows me to do tolerance checks on collections. Refer to the Equal Constraint. One uses the AsCollection and Within extension methods. On that note though I am not 100% sure regarding the implications of this statement made
If you want to treat the arrays being compared as simple collections,
use the AsCollection modifier, which causes the comparison to be made
element by element, without regard for the rank or dimensions of the
array.
[Test]
//[ExpectedException()]
public void CheckLists_FailsAt0()
{
var expected = new[] { 0.0001, 0.4353245, 1.3455234, 345345.098098 };
var result1 = new[] { -0.0004, 0.43520, 1.3454, 345345.0980 };
Assert.That(result1, Is.EqualTo(expected).AsCollection.Within(0.0001), "fail at [0]"); // fail on [0]
}
[Test]
//[ExpectedException()]
public void CheckLists_FailAt1()
{
var expected = new[] { 0.0001, 0.4353245, 1.3455234, 345345.098098 };
var result1a = new[] { 0.0001000000 , 0.4348245000 , 1.3450234000 , 345345.0975980000 };
Assert.That(result1a, Is.EqualTo(expected).AsCollection.Within(0.0001), "fail at [1]"); // fail on [3]
}
[Test]
public void CheckLists_AllPass_ForNegativeDiff_of_1over10001()
{
var expected = new[] { 0.0001, 0.4353245, 1.3455234, 345345.098098 };
var result2 = new[] { 0.00009900 , 0.43532350 , 1.34552240 , 345345.09809700 };
Assert.That(result2, Is.EqualTo(expected).AsCollection.Within(0.0001)); // pass
}
[Test]
public void CheckLists_StillPass_ForPositiveDiff_of_1over10001()
{
var expected = new[] { 0.0001, 0.4353245, 1.3455234, 345345.098098 };
var result3 = new[] { 0.00010100 , 0.43532550 , 1.34552440 , 345345.09809900 };
Assert.That(result3, Is.EqualTo(expected).AsCollection.Within(0.0001)); // pass
}
NUnit does not define any delegate object or interface to perform custom checks to lists, and determine that a expected result is valid.
But I think that the best and simplest option is writing a small static method that achieve your checks:
private const float MIN_ACCEPT_VALUE = 0.0001f;
public static void IsAcceptableDifference(IList collection, IList oldCollection)
{
if (collection == null)
throw new Exception("Source collection is null");
if (oldCollection == null)
throw new Exception("Old collection is null");
if (collection.Count != oldCollection.Count)
throw new Exception("Different lenghts");
for (int i = 0; i < collection.Count; i++)
{
float newValue = (float)collection[i];
float oldValue = (float)oldCollection[i];
float difference = Math.Abs(oldValue - newValue);
if (difference < MIN_ACCEPT_VALUE)
{
throw new Exception(
string.Format(
"Found a difference of {0} at index {1}",
difference,
i));
}
}
}
You've asked how to achieve your desired test using a CollectionAssert method without looping through the list. I'm sure this is obvious, but looping is exactly what such a method would do...
The short answer to your exact question is that you can't use CollectionAssert methods to do what you want. However, if what you really want is an easy way to compare lists of floating point numbers and assert their equality, then read on.
The method Assert.AreEqual( double expected, double actual, double tolerance ) releases you from the need to write the individual item assertions yourself. Using LINQ, you could do something like this:
double delta = 0.0001;
IEnumerable<double> expectedValues;
IEnumerable<double> actualValues;
// code code code
foreach (var pair in expectedValues.Zip(actualValues, Tuple.Create))
{
Assert.AreEqual(pair.Item1, pair.Item2, delta, "Collections differ.");
}
If you wanted to get fancier, you could pull this out into a method of its own, catch the AssertionException, massage it and rethrow it for a cleaner interface.
If you don't care about which items differ:
var areEqual = expectedValues
.Zip(actualValues, Tuple.Create)
.Select(tup => Math.Abs(tup.Item1 - tup.Item2) < delta)
.All(b => b);
Assert.IsTrue(areEqual, "Collections differ.");
I have the following classes with an implicit cast operator defined:
class A
{
...
}
class B
{
private A m_a;
public B(A a)
{
this.m_a = a;
}
public static implicit operator B(A a)
{
return new B(a);
}
}
Now, I can implicitly cast A to B.
But why can't I implicitly cast A[] to B[] ?
static void Main(string[] args)
{
// compiles
A a = new A();
B b = a;
// doesn't compile
A[] arrA = new A[] {new A(), new A()};
B[] arrB = arrA;
}
Thanks, Malki.
As Mehrdad Afshari mentioned, you're out of luck doing this implicitly. You'll have to get explicit, and it'll involve an array copy. Thankfully, you can probably do it with a one-liner:
arrB = arrA.Cast<B>().ToArray();
Although if you only want to iterate arrB in a foreach statement, you can avoid the copy by omitting ToArray()
Array covariance only works for reference types and in the inheritance hierarchy (note that it's not a representation-changing conversion: just a set of pointers with identical size interpreted differently.) It will not work for value types and user defined conversions.
ConvertAll
Just to be explicit, here is how you use ConvertAll.
In the case where class B has a member of class A called m_a, do this:
B[] arrB;
A[] arrA = Array.ConvertAll(arrB, b => b.m_a);
.
If class B has some member data that you need to manipulate before you can return an object of type A (such as turning a bunch of numerical values into a string description), do this:
class B
{
public static A makeAfromB(B b)
{
// Do something with B data...
A a = new A("data made from B data")
return a;
}
// rest of class B implementation ...
}
// somewhere else in your code...
A[] arrA = Array.ConvertAll(arrB, new Converter<B, A>(B.makeAfromB));
.
You can also use Lambda functions:
A[] arrA = Array.ConvertAll(arrB, new Converter<B, A>(
delegate(B b)
{
// Do something with B data, though object b is const
A a = new A("data made from B data")
return a;
}));
.
It would be nice if ConvertAll could use the implicit operator to do the conversion, but I haven't figured out how to do that.
.
Cast
#Randolpho #bottlenecked
For the cases where you simply want to iterate and would prefer not to make a copy, using cast makes sense. However I have been unable to make it work.
I have an InkPoint class which has a Point object and some other members. I want to call the DrawLines(Pen, Point[]) function. However, I have an array of InkPoint[].
Here is my class and the code I currently have to use, which makes a copy:
public class InkPoint
{
public InkPoint(int x, int y)
{
point = new Point(x, y);
}
public Point point { get; set; }
public static implicit operator Point(InkPoint p)
{
return p.point;
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
InkPoint[] inkPoints = { new InkPoint(1,2), new InkPoint(3,4) };
Point[] points = Array.ConvertAll(inkPoints, x => x.point);
Pen pen = new Pen(Color.Black, 1);
e.Graphics.DrawLines(pen, points);
}
.
I would rather call this, but it won't compile, citing invalid arguments:
e.Graphics.DrawLines(pen, inkPoints.Cast<Point>()); // Compile err: invalid args
.
I've also tried iterating over a cast, but it throws an exception, citing the cast is not valid
foreach (Point p in inkPoints.Cast<Point>()) { } // Exception: cast not valid
.
I don't understand why the specified cast is not valid since I've defined an implicit operator. I'm able to do the following just fine:
InkPoint ip = new InkPoint(10, 20);
Point p1 = ip; // implicit conversion
Point p2 = (Point)ip; // cast
.
For me, the situation is actually slightly more complicated than that. I actually have a list of InkPoints, List<InkPoint>, but the DrawLines function accepts only arrays. So my code looks like this:
List<InkPoint> inkPoints = new List<InkPoint>();
inkPoints.Add(new InkPoint(5, 10));
inkPoints.Add(new InkPoint(10, 15));
Point[] points = inkPoints.ConvertAll<Point>(x => x.point).ToArray();
I can rearrange it slightly to this:
Point[] points = Array.ConvertAll(inkPoints.ToArray(), x => x.point);
.
So I think there's actually two copies happening here. This is annoying since all I want to do is draw the lines. It doesn't seem unreasonable that the DrawLines function should be able to iterate over some array/list that contains references to objects that can be implicitly converted to Point objects.
Imagine for a moment if Arrays used the same syntax as other collections in .Net, and what you're trying to compare is an Array<A> with an Array<B>. You wouldn't compare a List<A> to a List<B>. Well, that's essentially what you're trying.
I'd recommend using a simple extension method to get the result you want, you'll need to change your syntax slightly to say 'B[] arrB = arrA.ToBArray();`
static class ArrayCast {
public static B[] ToBArray(this A[] source) {
var result = new B[source.Length];
for (int i = 0;i < source.Length;i++)
result[i] = source[i];
return result;
}
}