Reputation: 43
My basic requirements are:
(I think I'd actually settle for the ability to just add and remove the sorted duplicate values without storing their associated objects, if this makes things any easier.)
Note #1: I've been using the IComparer implementation for duplicate keys as recommended here: C# Sortable collection which allows duplicate keys
However, I run into a problem when I want to remove an object. Since I'm using a custom IComparer object, the dictionary or list fails to find the object by its intrinsic IComparer implementation.
Note #2: I've also tried using the PowerCollections OrderedMultiDictionary class. This didn't bring me much closer to a solution, as I still have to choose between the ability to have duplicate keys (via a custom IComparer implementation) and being able to remove objects from the collection afterwards.
Upvotes: 2
Views: 3444
Reputation: 61
You cas use Distinct overriding first the equals method, example:
public void TestMethod1 ( )
{
List<Model> listmodel = new List<Model>( )
{
new Model() { Prop1 = "one", Prop2 = 2 },
new Model() { Prop1 = "one", Prop2 = 6 },
new Model() { Prop1 = "two", Prop2 = 1 },
new Model() { Prop1 = "three", Prop2 = 7 },
new Model() { Prop1 = "four", Prop2 = 6 },
};
var output = listmodel.Distinct( ).ToList( );
output.ToList( ).ForEach( x => Console.WriteLine( x.ToString( ) ) );
}
public class Model
{
public string Prop1 { get; set; }
public int Prop2 { get; set; }
public string Prop3 { get; set; }
public string Prop4 { get; set; }
public override bool Equals ( object obj )
{
Model casted = obj as Model;
if (casted == null) return false; //If cast an object to my model is null, is not my model and is not equal
if (casted.Prop1 == this.Prop1) return true; //My logic define if the input.Prop1 is equal to my Prop1, this is equal
return false;
}
public override int GetHashCode ( )
{
return 1;
}
public override string ToString ( )
{
return $"{this.Prop1} - {this.Prop2} - {this.Prop3} - {this.Prop4}";
}
}
Output:
one - 2 - -
two - 1 - -
three - 7 - -
four - 6 - -
If you need the lower, you can modify the line:
var output = listmodel.Distinct( ).ToList( );
To this:
var output = listmodel.OrderByDescending(x=> x.Prop2).Distinct( ).ToList( );
The output change:
three - 7 - -
one - 6 - -
four - 6 - -
two - 1 - -
Upvotes: 0
Reputation: 15091
From the MS docs for List "Represents a strongly typed list of objects that can be accessed by index. Provides methods to search, sort, and manipulate lists." As you can see duplicate properties are not a problem. I made a little class. It could have been a structure. In the main program I created a List and added the objects. I hope this mets most of your requirements. When removing items from the list iterating through the list use a for loop backwards because indexes change when items are removed.
private void TestList()
{
List<SomeObject> lst = new List<SomeObject>();
//Add to the list
lst.Add(new SomeObject("Mary", "Jones", 50));
lst.Add(new SomeObject("John", "Smith", 42));
lst.Add(new SomeObject("James", "Peterson",50));
lst.Add(new SomeObject("Mary", "Hanes", 62));
//Sort the list
var sortedByAge = from obj in lst orderby obj.Age select obj;
Debug.Print("*****List Sorted by Age*****");
foreach (SomeObject obj in sortedByAge)
Debug.Print($"{obj.FirstName} {obj.LastName}'s age is {obj.Age}");
var sortByLastName = from obj in lst orderby obj.LastName select obj;
Debug.Print("*****List Sorted by LastName*****");
foreach (SomeObject obj in sortByLastName)
Debug.Print($"{obj.LastName}, {obj.FirstName}");
//Delete from list
for (int i = lst.Count - 1; i > -1; i--)
if (lst[i].FirstName == "Mary")
{ lst.RemoveAt(i); }
Debug.Print("*****List after Deletes*****");
foreach (SomeObject item in lst)
Debug.Print($"{item.FirstName} {item.LastName} {item.Age}");
}
public class SomeObject
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public SomeObject(string fname, string lname, int age)
{
FirstName = fname;
LastName = lname;
Age = age;
}
}
Upvotes: 2