C#排序的集合,允许重复的键(或值),并允许我删除项目

时间:2018-07-07 06:30:08

标签: c# sorting collections duplicates

我的基本要求是:

  1. 我需要能够将对象添加到集合中,并根据我选择的对象属性进行排序,知道该属性的值可能会出现多次。
  2. 我需要稍后能够从此集合中删除对象,最好使用已排序对象中内置的IComparer实现。

(我想我真的会接受只添加和删除排序的重复值而不存储它们的关联对象的功能,如果这样做会使事情变得更容易的话。)

注释1: 我一直在将IComparer实现用于重复的键,如此处建议的那样: C# Sortable collection which allows duplicate keys

但是,当我要删除对象时遇到问题。由于我使用的是自定义IComparer对象,因此字典或列表无法通过其固有的IComparer实现找到该对象。

注释#2:我也尝试使用PowerCollections OrderedMultiDictionary类。这并没有使我更接近解决方案,因为我仍然必须在具有重复键的功能(通过自定义IComparer实现)与之后能够从集合中删除对象之间进行选择。

2 个答案:

答案 0 :(得分:1)

从MS文档获取列表 “表示索引可以访问的对象的强类型列表。提供搜索,排序和操作列表的方法。” 如您所见,重复的属性不是问题。 我上了一堂课。可能是一个结构。在主程序中,我创建了一个列表并添加了对象。我希望这可以满足您的大多数要求。 当从列表中删除项目时,遍历该列表,请使用for后退循环,因为删除项目时索引会更改。

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;
            }
        }

答案 1 :(得分:0)

您可以先使用Distinct覆盖equals方法,例如:

    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}";
        }

    }

输出:

one - 2 -  - 
two - 1 -  - 
three - 7 -  - 
four - 6 -  -

如果需要下排,可以修改以下行:

var output = listmodel.Distinct(  ).ToList( );

对此:

var output = listmodel.OrderByDescending(x=> x.Prop2).Distinct(  ).ToList( );

输出更改:

three - 7 -  - 
one - 6 -  - 
four - 6 -  - 
two - 1 -  -