At least one one object must implement Icomparable

10,093

Solution 1

Here I get the IDs in an anonymous type to make it readable.

var patientEncounters= from patient in PatientList
                       let PatientID=Int32.Parse(patient.Value.Split('|')[0])
                       let EncounterID=Int32.Parse(patient.Value.Split('|')[1])
                       select new { PatientID, EncounterID };

Then we group by UserID and get the last encounter

var lastEncounterForEachUser=from pe in patientEncounters
                             group pe by pe.PatientID into grouped
                             select new 
                                    { 
                                        PatientID=grouped.Key,
                                        LastEncounterID=grouped.Max(g=>g.EncounterID)
                                    };

Solution 2

Linq doesn't know how to compare 2 Patient objects, so it can't determine which one is the "greatest". You need to make the Patient class implement IComparable<Patient>, to define how Patient objects are compared.

// Compare objets by Id value
public int CompareTo(Patient other)
{
    return this.Id.CompareTo(other.Id);
}

Another option is to use the MaxBy extension method available in Jon Skeet's MoreLinq project:

var queryResults = PatientList.GroupBy(x => x.Value.Split('|')[1])
                              .Select(x => x.MaxBy(p => p.Id));

EDIT: I assumed there was a Patient class, but reading your code again, I realize it's not the case. PatientList is actually a collection of SelectListItem, so you need to implement IComparable in that class.

Share:
10,093
SoftwareSavant
Author by

SoftwareSavant

Software developer 8 years of Software Development experience Have held jobs writing: Java, .Net Code (C#, VB), Javascript (React.js, JQuery) and PHP MSSQL Server queries, views, stored procs and some table design Oracle 10g queries, views, stored procs... No database design experience using Oracle. Prior to my positions in development held jobs on a helpdesk level and on network engineering basis (real simple stuff there)... using System.Web.TehForums; public static void main(string[] args) { System.Console.WriteLine("Hello World"); }

Updated on August 22, 2022

Comments

  • SoftwareSavant
    SoftwareSavant over 1 year

    I am attempting to get unique values in a list of similar value distinguished only by a one element in a pipe delimited string... I keep getting at least one object must implement Icomparable. I don't understand why I keep getting that. I am able to groupBy that value... Why can't I find the max... I guess it is looking for something to compare it with. If I get the integer version will it stop yelling at me? This is the last time I am going to try using LINQ...

        var queryResults = PatientList.GroupBy(x => x.Value.Split('|')[1]).Select(x => x.Max());
    

    I know I can get the unique values some other way. I am just having a hard time figuring it out. In that List I know that the string with the highest value amongst its similar brethren is the one that I want to add to the list. How can I do that? I am totally drawing a blank because I have been trying to get this to work in linq for the last few days with no luck...

        foreach (XmlNode node in nodeList)
                {
                    XmlDocument xDoc = new XmlDocument();
                    xDoc.LoadXml(node.OuterXml);
                    string popPatInfo = xDoc.SelectSingleNode("./template/elements/element[@name=\"FirstName\"]").Attributes["value"].Value + ", " + xDoc.SelectSingleNode("./template/elements/element[@name=\"LastName\"]").Attributes["value"].Value + " | " + DateTime.Parse(xDoc.SelectSingleNode("./template/elements/element[@name=\"DateOfBirth\"]").Attributes["value"].Value.Split('T')[0]).ToString("dd-MMM-yyyy");
                    string patientInfo = xDoc.SelectSingleNode("./template/elements/element[@name=\"PatientId\"]").Attributes["value"].Value + "|" + xDoc.SelectSingleNode("./template/elements/element[@name=\"PopulationPatientID\"]").Attributes["enc"].Value;// +"|" + xDoc.SelectSingleNode("./template/elements/element[@name=\"AdminDate\"]").Attributes["value"].Value;
                    int enc = Int32.Parse(patientInfo.Split('|')[1]);
                    if (enc > temp)
                    {
                        lastEncounter.Add(enc, patientInfo);
                        temp = enc;
                    }
                    //lastEncounter.Add(Int32.Parse(patientInfo.Split('|')[1]));
    
                    PatientList.Add( new SelectListItem { Text = popPatInfo, Value = patientInfo });
                }
    

    I was thinking about using some kind of temp variable to find out what is the highest value and then add that string to the List. I am totally drawing a blank however...