Set property if exists in another list - c#

I have two lists of type Derp:
public class Derp
{
public bool Valid;
public int SomeValue;
public int MoreValues;
public int EvenMoreValues;
public int ThereAreManyValues;
}
List<Derp> a = new List<Derp>();
List<Derp> b = new List<Derp>();
/// Populate both
var c = a.Intersect(b).Select(x=> { x.Valid = true; return x; });
I need to set Valid to true if b exists in a and keep all values in a. I can understand that the snippet above only keeps the intersected objects, but I need to retain a.
I've tried other funny things too (var c = a.Where(x => b.Contains(x)).Sel...) but I don't think I understand the List methods enough to solve this one.

Try this:
b.ForEach(x => {if (a.Contains(x)) {x.Valid = true;} });
The above works. However, do take note of #SriramSakthivel's comments and reconsider your approach if possible.
Demo

Related

Why original value changes if I am processing a copy of it?

I am using this routine to load some coordinates into a container, draw them, zoom into them and these sort of tasks. Then at a button click, I tend to Reset everything to the original or initial state. To do that I take a copy of the initial and play with the copy. But on Reset button click, I destroy the copy, take a new copy of the initial and process it. And so on.
For some reason, the original container changes when I change the copy. Could anyone spot what am I doing wrong?
In order, I load the data first and take a copy:
// CoordPoint is a simple xy point
public List<CoordPoint> MyLoadedCoords { get { return myLoadedCoords; } set { myLoadedCoords = value; }}
public List<CoordPoint> MyDisplayedCoords { get { return myDisplayedCoords; } set { myDisplayedCoords = value }}
private List<CoordPoint> myLoadedCoords;
private List<CoordPoint> myDisplayedCoords;
//..
public void LoadData()
{
// load points from file
MyLoadedCoords = File.ReadLines("C:\\...\\Samples.txt")
// get a copy of original coords
MyDisplayedCoords = MyLoadedCoords.ToList();
}
Note that MyLoadedCoords exists no where in the code expect here (And in the Reset function, down). Then I process the copy MyDisplayedCoords several places similar to this:
public void UpdateDisplayPosition()
{
for (var i = 0; i < MyDisplayedCoords.Count; i++)
{
MyDisplayedCoords[i].X += XCoordOffset; //some processed values
MyDisplayedCoords[i].Y += YCoordOffset; //some processed values
}
}
Reset Button I do this:
public void ResetZoom()
{
MyDisplayedCoords = MyLoadedCoords.ToList(); // I set break point here
AdjustInitialDisplayPosition();
DrawImage();
}
ResetZoom() does not do what is expected, When I debug and break on MyDisplayedCoords = MyLoadedCoords; I see that MyLoadedCoords contains the exact same values/objects as MyDisplayedCoords
EDIT:
I implemented IClonable and "overrided" the Clone() function in my class but it did NOT work:
public class CoordPoint : ICloneable
{
// ..
public object Clone()
{
return new CoordPoint {X = X, Y = Y, Z = Z, Color = Color};
}
}
However, without the IClonable, this "copying" works as cloning as H.B answered:
MyDisplayedCoords = MyLoadedCoords.Select(c => new CoordPoint { X = c.X, Y = c.Y, Z = c.Z, Color = c.Color }).ToList();
MyDisplayedCoords = MyLoadedCoords does not copy anything, it assigns a reference to the same object to a property, now both properties point to the same object.
To copy a list you could use on of the Linq methods (which always return a new list):
MyDisplayedCoords = MyLoadedCoords.ToList();
To deep copy you could do something like this, then the instances in the lists will also be different:
MyDisplayedCoords = MyLoadedCoords.Select(c =>
new CoordPoint { X = c.X, Y = c.Y }).ToList();
To add on H.B's answer,
ToList creates a new List object, but the objects inside the lists are just references to the same object unless they're immutable objects(string for example or primitive types).
Your original List object will not be affected in this case (addition of new objects/removals etc.) but changes to objects will reflect in both. Because they refer same object.
You can either follow H.B's answer to copy new as new objects or follow the below process which is more clean and proper.
Implement ICloneable interface in CoordPoint class. override the Clone method and call it during copying. A bit long method, but this way your code Linq will look proper.
public class CoordPoint : ICloneable
{
//rest of your code here
public object Clone()
{
return new CoordPoint
{
X= X,
Y = Y
};
}
}
Then your Linq code will be,
MyDisplayedCoords = MyLoadedCoords.Select(c => (CoordPoint)c.Clone()).ToList();
When you 'copy' your list object you are getting a new list, but the items in that list are all still pointing to the same items as the first.
The easiest way to to get around this problem is the ICloneable interface, here is a short sample:
public class MyObject : ICloneable
{
public string Property { get; set; }
public object Clone()
{
return this.MemberwiseClone();
}
}
Usage:
var list = new List<MyObject>() { new MyObject { Property = "FirstObject" } };
var clonedList = list.Select(x => x.Clone());

Compare c# Complex objects

I am wondering about the best approach to the below
I have a .NET Web application and I am changing the ORM provider I am using. To do this I have created a new solution and removed the previous ORM and implemented my new one. As there are lots of existing screens that work with the previous ORM I want to make sure that the same object is returned by both ORMS. As these are in two separate VS slns is there a simple way I can compare the complex objects that all the same properties have been loaded on to the object graph. I could set a breakpoint and compare them manually but I don't really want to do this?
If this is for testing purposes, you can use FluentAssertions to check this.
The following code declares two unrelated types, ClassA and ClassB which contain two nested classes both called A and B but of different types.
Therefore the containing classes and the nested classes are of unrelated types, but the names of the members are the same, and for the nested classes the types of the properties are the same.
You can use FluentAssertions to test if the two instances classA and classB are equivalent - even though they are of different types - as follows:
using System;
using FluentAssertions;
namespace Demo
{
class ClassA
{
public NestedClassA A;
public NestedClassB B;
}
class NestedClassA
{
public string S;
public int I;
}
class NestedClassB
{
public char C;
public double D;
}
class ClassB
{
public NestedClassC A;
public NestedClassD B;
}
class NestedClassC
{
public string S;
public int I;
}
class NestedClassD
{
public char C;
public double D;
}
internal class Program
{
private static void Main()
{
var nestedA = new NestedClassA {I = 1, S = "1"};
var nestedB = new NestedClassB {C = '1', D = 1};
var nestedC = new NestedClassC { I = 1, S = "1" };
var nestedD = new NestedClassD { C = '1', D = 1 };
var classA = new ClassA {A = nestedA, B = nestedB};
var classB = new ClassB {A = nestedC, B = nestedD};
classA.ShouldBeEquivalentTo(classB); // Passes
classB.ShouldBeEquivalentTo(classA); // Passes
classB.B.D = 2; // Now the two objects do not contain equivalent data.
classA.ShouldBeEquivalentTo(classB); // Fails.
}
}
}
So I am guessing it is not as simple as to implement the IEquatable interface and directly compare your instances using this. You have to be aware that implementing proper comparing methods will be the fastest way.
But there are slower, more flexible ways. I think what you want to do is:
Compare two objects of unknown types
Check if they contain class variables with the same name
Check if the class variables have matching types
Check if the values in the variables are the same
There is only one way to do that. And it is to throw System.Reflection at the problem. Mind that this solution will be considerably slower then all solutions that work with known types.
So you need your ComplexEquals function.
public static bool ComplexEquals(object obj1, object obj2)
{
if (obj1 == null && obj2 == null) return true;
if (obj1 == null || obj2 == null) return false;
var obj1Class = obj1.GetType();
var obj2Class = obj2.GetType();
/* Get the instance fields (all of them) of both classes. */
var obj1Fields = obj1Class.GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public);
var obj2Fields = obj2Class.GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public);
var checkedFields = new HashSet<String>();
foreach (var obj1Field in obj1Fields)
{
var fieldName = obj1Field.Name;
checkedFields.Add(fieldName);
var obj2Field = obj2Fields.Where(f => f.Name == fieldName).SingleOrDefault();
if (obj2Field == null) return false;
if (obj1Field.FieldType == obj2Field.FieldType && !(obj1Field.GetValue(obj1).Equals(obj2Field.GetValue(obj2)))) return false;
}
if (obj2Fields.Any(f => !checkedFields.Contains(f.Name))) return false;
return true;
}
This is a simple version that relies on the Equals function starting at the first level inside the unknown function. This may be sufficient or not. But I think that is a starting point that can be extended if required.

C# Linq intersect/except with one part of object

I've got a class:
class ThisClass
{
private string a {get; set;}
private string b {get; set;}
}
I would like to use the Intersect and Except methods of Linq, i.e.:
private List<ThisClass> foo = new List<ThisClass>();
private List<ThisClass> bar = new List<ThisClass>();
Then I fill the two lists separately. I'd like to do, for example (and I know this isn't right, just pseudo code), the following:
foo[a].Intersect(bar[a]);
How would I do this?
If you want a list of a single property you'd like to intersect then all the other pretty LINQ solutions work just fine.
BUT! If you'd like to intersect on a whole class though and as a result have a List<ThisClass> instead of List<string> you'll have to write your own equality comparer.
foo.Intersect(bar, new YourEqualityComparer());
same with Except.
public class YourEqualityComparer: IEqualityComparer<ThisClass>
{
#region IEqualityComparer<ThisClass> Members
public bool Equals(ThisClass x, ThisClass y)
{
//no null check here, you might want to do that, or correct that to compare just one part of your object
return x.a == y.a && x.b == y.b;
}
public int GetHashCode(ThisClass obj)
{
unchecked
{
var hash = 17;
//same here, if you only want to get a hashcode on a, remove the line with b
hash = hash * 23 + obj.a.GetHashCode();
hash = hash * 23 + obj.b.GetHashCode();
return hash;
}
}
#endregion
}
Maybe
// returns list of intersecting property 'a' values
foo.Select(f => f.a).Intersect(bar.Select(b => b.a));
BTW property a should be public.
Not sure of the speed of this compared to intersect and compare but how about:
//Intersect
var inter = foo.Where(f => bar.Any(b => b.a == f.a));
//Except - values of foo not in bar
var except = foo.Where(f => !bar.Any(b => b.a == f.a));
foo.Select(x=>x.a).Intersect(bar.Select(x=>x.a))
What exactly is the desired effect? Do you want to get a list of strings composed of all the a's in your classes, or a list of ThisClass, when two ThisClass instances are identified via unique values of a?
If it's the former, the two answers from #lazyberezovksy and #Tilak should work. If it's the latter, you'll have to override IEqualityComparer<ThisClass> or IEquatable<ThisClass> so that Intersect knows what makes two instances of ThisClass equivalent:
private class ThisClass : IEquatable<ThisClass>
{
private string a;
public bool Equals(ThisClass other)
{
return string.Equals(this.a, other.a);
}
}
then you can just call:
var intersection = foo.Intersect(bar);
I know this is old but couldn't you also just override the Equals & GetHashCode on the class itself?
class ThisClass
{
public string a {get; set;}
private string b {get; set;}
public override bool Equals(object obj)
{
// If you only want to compare on a
ThisClass that = (ThisClass)obj;
return string.Equals(a, that.a/* optional: not case sensitive? */);
}
public override int GetHashCode()
{
return a.GetHashCode();
}
}
You should create IEqualityComparer. You can pass the IEqualityComparer to Intersect() method. This will help you get List(which intersect with bar) easier.
var intersectionList = foo.Intersect(bar, new ThisClassEqualityComparer()).ToList();
class ThisClassEqualityComparer : IEqualityComparer<ThisClass>
{
public bool Equals(ThisClass b1, ThisClass b2)
{
return b1.a == b2.a;
}
public int GetHashCode(Box bx)
{
// To ignore to compare hashcode, please consider this.
// I would like to force Equals() to be called
return 0;
}
}

Dynamically add values to List<double> using get & set

Is it possible to do somethink like
public class TestClass
{
public List<double> preTvoltage
{
get
{
return preTvoltage;
}
set
{
preTvoltage.Add(this); //how to add to the List??
}
}
}
The reason I want to do this (I do not know if this is a best method, just as far as my knowledge allows) because I have to get data from xml files that do not have always same number of data in them.
Later I want to fill a ListView rows and using list I can count how many items are and how many columns will be needed.
Here is a schematic of xml file:
and there are also Trigger and PostTrigger nodes in xml file with same data sorting.
and here is the listview I want to achive:
Link to full size image
So, there are some pin groups and each pingroup has lots of data, the above code I gave, was just to hold 1 of the voltage nodes in xml file.
I am pretty much listening for your ideas!
Thanks.
No, and it defies usage of properties - you should implement it as an Add (or similarly aptly named) method.
You can't add this, because this is a TestClass, not a double; and you can't add value, as otherwise suggested, because that is a List<double>, and Add requires a double.
It's not clear how you would use this, but it looks like a very bad idea to me. Setting a collection as a property is slightly unusual already, but it's even odder for that set operation to mutate the list. It's additionally weird that you're not using the value variable within the setter... why not?
You should consider what the calling code would look like, and whether that's really the clearest way of expressing the semantics you want.
set { preTvoltage.AddRange(value); }
As Jon Skeet is saying, this is not what you should do. Instead, do
TestClass t = new TestClass();
t.PreTvoltage.Add(...);
declaring the property as
public List<double> PreTvoltage
{
get { return preTvoltage; }
}
The type of a getter and setter must match.
You could have:
public List<double> preTvoltage
{
get
{
return preTvoltage;
}
set
{
preTvoltage.AddRange(value); //add all items in list assigned.
}
}
However, this seems like a bad idea as it would be confusing to users why the value got did not match the value just set. I would have the two operations as separate members, and the setter either not exist or else overwrite the existing preTvoltage entirely.
You can not implement it like this, the preferable way is to make collection controls like:
private IList<double> _preTvoltage = new List<double>();
public IEnumerable<double> preTvoltage
{
get
{
return preTvoltage.AsEnumerable();
}
}
public void AddTvoltage(double item)
{
_preTvoltage.Add(item);
}
Well I managed to solve my problem this way:
public class ITestData
{
public string pinName { get; set; } //Name of the pin
public double stressLevel { get; set; } //Stress level for latchup
public int psuCount { get; set;} //Number of PSU's
public List<double[]> preTrigger = new List<double[]>();
public List<double[]> inTrigger = new List<double[]>();
public List<double[]> postTrigger = new List<double[]>();
public void AddPreTrigger(double volt, double curr)
{
double[] data = new double[2];
data[0] = volt;
data[1] = curr;
preTrigger.Add(data);
}
public void AddInTrigger(double volt, double curr)
{
double[] data = new double[2];
data[0] = volt;
data[1] = curr;
inTrigger.Add(data);
}
public void AddPostTrigger(double volt, double curr)
{
double[] data = new double[2];
data[0] = volt;
data[1] = curr;
postTrigger.Add(data);
}
}

Returning data from one method to another within a class

Thanks for help with the question I just submitted about anonymous classes. Now I understand more. Here's a bit more of an example:
public class abc {
public xx doAction() {
return ( new { ID = 5, Name= "Dave" } );
}
public void doStart() {
var a = doAction();
var b = a.ID;
var c = a.Name;
}
}
So am I correct in saying that the most ideal way to do this would be to declare a class XYX and use it like this:
public class abc {
public XYZ doAction() {
return ( new XYZ { ID = 5, Name= "Dave" } );
}
public void doStart() {
var a = doAction();
var b = a.ID;
var c = a.Name;
}
}
The class would be only used for this one data transfer between the two methods.
I think you meant: return new XYZ(5, "Dave")
Anyways, your solution is okay but there is no reason to create a new class simply to share data. You can use a hashtable/array/dictionary or whatever class suits you best to share data. If you want to do something special with the XYZ class, or it has methods you wish to call from it, then you would have to create a new class XYZ and return it. Though, if you just want to share data, use a data structure that's already available to your use.
That would work yes. If it is the most ideal or not is hard to say. Since you are using the variables "ID" and "Name" it kinda indicates that you are working with domain objects from a database, and if so, you will probably need the class for a lot more than just this one method.
What about the class ABC? What kind of class is that? Because you could also do this:
public class abc{
private int _id;
private string _name;
public void DoAction(){
_id = 5;
_name = "Dave";
}
public void DoStart(){
var b = _id;
var c = _name;
}
}
But remember to use proper naming for your classes, so you have an idea of what they are used for.
Yes, though if your class has trivial properties you can consider using existing .Net classes:
1) You can consider using System.Tuple (.Net 4.0) but you will not have good property names anymore:
var result = Tuple.Create(5, "Dave");
int id = result.Item1;
string name = result.Item2;
2) You can use KeyValuePair if it is applicable:
var result = new KeyValuePair<int, string>(5, "Dave");
int id = result.Key;
string name= result.Value;

Categories