juleekwin
juleekwin

Reputation: 531

Comparing objects from two instances of a Class and storing result in List<class>

I pretty much asked this question yesterday, but i'm going to reform it as a new question and be more specific.

Here is the question I asked yesterday.

I have a list of a class type (ex. ESHClass)

List<ESHClass> eshlist;

And ESHClass is composed of elements like:

public class ESHClass{
  public string PolicyNumber;
  public string PolicyMod;
  public string MultiPolicy;
  public string HasSwimmingPool;
};

So say eshlist has to policies(ESHClass) and there values equal:

eshlist[0].PolicyNumber= "7";
eshlist[0].PolicyMod= "00";
eshlist[0].MultiPolicy= "Yes";
eshlist[0].HasSwimmingPool= "No";

eshlist[1].PolicyNumber= "7";
eshlist[1].PolicyMod= "00";
eshlist[1].MultiPolicy= "No";
eshlist[0].HasSwimmingPool= "Yes";

So I have two instances of my ESHClass that the data has been set and they are being stored in eshlist.

The next part is where my other post got warry. I want to compare the objects like:

eshlist[0].PolicyNumber == eshlist[1].PolicyNumber //I know this isn't correct code its 
                                                   //just to show how I would compare.

eshlist[0].HasSwimmingPool == eshlist[1].HasSwimmingPool

and then if the two objects i'm comparing are different I want to keep them in a list to print them on my webpage which I made with MVC 4 and the page is a ListView.

My post from yesterday was asking more about doing this in the most efficient way...today I got to thinking about it and idk if i'll really be able to get away from doing it for each element... right now this is now i'm doing it:

public List<ESHList> Compare(List<ESHClass> polList)
        {
            var l = polList;
            if (l[0].PolicyNumber.Equals(l[1].PolicyNumber))
                l[0].PolicyNumber = l[1].PolicyNumber = null;
            if (l[0].HasSwimmingPool.Equals(l[1].HasSwimmingPool))
                l[0].HasSwimmingPool = l[1].HasSwimmingPool= null;
    }

So all the equal elements are nulled out and only the different elements are returned in the list. This is where i'm calling the Compare method:

Index.cshtml:

{
 ...
 return View((esh.Compare(eshList)).DefaultIfEmpty());
}

So now after showing a more detailed explanation do you think there's a way to get away from a long series of ifs or just a better way to do what i'm trying today yet keep the result in a list I can print on the screen? As I said in my other post i'm newer to C# and completely new to web programming. If you have any helpful answers or articles I could reference, please let me know! Thank you!

EDIT: Just to show using my example what my screen will show

Policy1

PolicyMod Yes HasSwimmingPool No

Policy2

PolicyMod No HasSwimmingPool Yes

Upvotes: 0

Views: 220

Answers (4)

juleekwin
juleekwin

Reputation: 531

After much research, I did end up using a series of if statements like I originally stated. It feels so icky though! :( Oh well!

Upvotes: 0

user153923
user153923

Reputation:

A good start would be to modify your ESHClass to implement IComparable:

public class ESHClass : IComparable<ESHClass> {

  public ESHClass() {
    TimeStamp = DateTime.MinValue;
  }

  public string PolicyNumber { get; set; }
  public string PolicyMod { get; set; }
  public string MultiPolicy { get; set; }
  public string HasSwimmingPool { get; set; }
  public DateTime TimeStamp { get; set; }

  public int CompareTo(ESHClass other) {
    int value = PolicyNumber.CompareTo(other.PolicyNumber);
    if (value == 0) {
      value = TimeStamp.CompareTo(other.TimeStamp);
    }
    return value;
  }

  public override string ToString() {
    return PolicyNumber;
  }

}

Now, to give that class some Horsepower, you could modify it to include a couple of const fields that should be set for your program and a static method to do all of the work:

private const string DEFAULT_FOLDER = @"C:\TEMP";
private const string FILE_EXTENSION = "*.xml";

public static ICollection<ESHClass> SortedPolicies() {
  var list = new List<ESHClass>();
  var dir = new DirectoryInfo(DEFAULT_FOLDER);
  foreach (var file in dir.GetFiles(FILE_EXTENSION)) {
    using (var xmlReader = System.Xml.XmlReader.Create(file.FullName)) {
      var esh = new ESHClass() { TimeStamp = file.CreationTime };
      try {
        while (xmlReader.Read()) {
          if (xmlReader.IsStartElement()) {
            switch (xmlReader.Name) {
              case "PolicyNumber":
                esh.PolicyNumber = xmlReader.Value;
                break;
              case "PolicyMod":
                esh.PolicyMod = xmlReader.Value;
                break;
              case "MultiPolicy":
                esh.MultiPolicy = xmlReader.Value;
                break;
              case "HasSwimmingPool":
                esh.HasSwimmingPool = xmlReader.Value;
                break;
            }
          }
        }
        list.Add(esh);
      } catch (Exception err) {
        throw err;
      } finally {
        xmlReader.Close();
      }
    }
  }
  list.Sort();
  return list;
}

You would need to modify that, of course, to match your XML structure!

This could be the complete class, all fused together:

public class ESHClass : IComparable<ESHClass> {

  private const string DEFAULT_FOLDER = @"C:\TEMP";
  private const string FILE_EXTENSION = "*.xml";

  public ESHClass() {
    TimeStamp = DateTime.MinValue;
  }

  public string PolicyNumber { get; set; }
  public string PolicyMod { get; set; }
  public string MultiPolicy { get; set; }
  public string HasSwimmingPool { get; set; }
  public DateTime TimeStamp { get; set; }

  public int CompareTo(ESHClass other) {
    int value = PolicyNumber.CompareTo(other.PolicyNumber);
    if (value == 0) {
      value = TimeStamp.CompareTo(other.TimeStamp);
    }
    return value;
  }

  public override string ToString() {
    return PolicyNumber;
  }

  public static ICollection<ESHClass> SortedPolicies() {
    var list = new List<ESHClass>();
    var dir = new DirectoryInfo(DEFAULT_FOLDER);
    foreach (var file in dir.GetFiles(FILE_EXTENSION)) {
      using (var xmlReader = System.Xml.XmlReader.Create(file.FullName)) {
        var esh = new ESHClass() { TimeStamp = file.CreationTime };
        try {
          while (xmlReader.Read()) {
            if (xmlReader.IsStartElement()) {
              switch (xmlReader.Name) {
                case "PolicyNumber":
                  esh.PolicyNumber = xmlReader.Value;
                  break;
                case "PolicyMod":
                  esh.PolicyMod = xmlReader.Value;
                  break;
                case "MultiPolicy":
                  esh.MultiPolicy = xmlReader.Value;
                  break;
                case "HasSwimmingPool":
                  esh.HasSwimmingPool = xmlReader.Value;
                  break;
              }
            }
          }
          list.Add(esh);
        } catch (Exception err) {
          throw err;
        } finally {
          xmlReader.Close();
        }
      }
    }
    list.Sort();
    return list;
  }

}

Upvotes: 0

Zenilogix
Zenilogix

Reputation: 1403

I don't think you can get away from "a long series of ifs" when you want to properly compare two instances of a complex object (as you might implement in an overload of Equals). But, bear the following in mind:

A logical expression in C# (such as the condition of an if statement) does not perform unnecessary evaluations i.e. it stops its evaluation as soon as it determines a result.

For example:

if (a && b && c) // won't evaluate b or c if a is false, won't evaluate c if b is false

Or:

if (a || b || c) // won't evaluate b or c if a is true, won't evaluate c if b is true

So, you could write a memberwise comparison as one big expression something like:

return ((this.a == that.a) && (this.b == that.b) && (this.c == that.c) /*... etc */);

...and you'd be sure that most of the comparisons won't even be performed if the first term is false.

Perhaps this will give you some guidance toward the appropriate solution.

Upvotes: 1

Bobson
Bobson

Reputation: 13706

The best way to do this is to make ESHClass know how to compare itself for equality.

See this link for a fairly in-depth example, or this question for a more minimal set.

Basically, you give the code enough information to be able to evaluate eshlist[0] == eshlist[1] directly.

Upvotes: 1

Related Questions