按字母顺序将项目插入C#列表中

17

请问有人可以教我如何在C#中按字母顺序将项目插入列表中吗?

所以每次添加到列表时,我想按字母顺序添加一个项目,理论上列表可能变得很大。

示例代码:

Public Class Person
{
     public string Name { get; set; }
     public string Age { get; set; }
}

Public Class Storage
{
    private List<Person> people;

    public Storage
    {
        people = new List<Person>();
    }


    public void addToList(person Person)
    {
        int insertIndex = movies.findindex(
            delegate(Movie movie) 
            {
              return //Stuck here, or Completely off Track.

            }
        people.insert(insertIndex, newPerson);
    }

}

1
在这里的 Stackoverflow 上:https://dev59.com/eXVC5IYBdhLWcg3wxEN1 - Đức Bùi
3
在适当的位置插入并不等同于在每次插入后重新排序列表。 - Kirk Broadhurst
使用专门的集合,例如sortedlist。在代码行数、错误率、CPU、内存、程序员时间等方面,List.Insert不是一种高效的解决方案。 - NPSF3000
2
Kirk - 我不知道我何时建议过它是。我的意图是找到一个现有的排序集合类,而不是找出如何对集合进行排序。 - John3136
5个回答

13

定义一个实现了 IComparer<T> 接口的比较器:

public class PersonComparer : IComparer<Person>
{
    public int Compare(Person x, Person y)
    {
        return x.Name.CompareTo(y.Name);
    }
}

使用SortedSet<T>,然后:

        SortedSet<Person> list = new SortedSet<Person>(new PersonComparer());
        list.Add(new Person { Name = "aby", Age = "1" });
        list.Add(new Person { Name = "aab", Age = "2" });
        foreach (Person p in list)
            Console.WriteLine(p.Name);
如果你受限于使用 .NetFramework3.5,你可以使用 SortedList<TKey, TValue> Class 然后:
SortedList<string, Person> list = 
          new SortedList<string, Person> (StringComparer.CurrentCulture);
Person person = new Person { Name = "aby", Age = "1" };
list.Add(person.Name, person);
person = new Person { Name = "aab", Age = "2" };
list.Add(person.Name, person);

foreach (Person p in list.Values)
    Console.WriteLine(p.Name);

特别是在 MSDN 文章的 Remarks 部分中阅读,比较这个类和SortedDictionary<TKey, TValue>


12

虽然这是一篇旧帖子,但我认为该帖中的答案忽略了楼主的实际问题。问题很简单,如何按排序顺序插入列表。这与“仅使用SortedSet / SortedList”不同。基于以下内容和使用SortedList会有不同的特点和影响。

SortedSet和SortedList都基于Dictionary,并且在我看来不允许您添加具有相同键的两个项目。

那么如何处理这样一个列表{a,b,c,c,d}?

这里是正确的将项目插入有序列表以保持顺序的方法:

var binarySearchIndex = list.BinarySearch(item, itemComparer);
//The value will be a negative integer if the list already 
//contains an item equal to the one searched for above
if (binarySearchIndex < 0)
{
    list.Insert(~binarySearchIndex, item);
}
else
{
    list.Insert(binarySearchIndex, item);
}

可以通过这篇很棒的2010年文章来回答:https://debugmode.net/2010/09/18/inserting-element-in-sorted-generic-list-list-using-binary-search/


非常好的回答,谢谢你!实际上回答了问题!我对itemComparer有点困惑;对我来说,我只是把它去掉,并确保我的'item'类实现了IComparable - undefined

5
如果您一定要使用列表,请尝试以下方法:
int loc;
for(loc = 0; loc < people.Count && people[loc].Name.CompareTo(personToInsert.Name) < 0; loc++);
people.Insert(loc, personToInsert);

您可以将 people[loc].Name.CompareTo(personToInsert.Name) < 0 替换为您要测试的任何条件 - 并且您可以更改符号使其降序而不是升序。例如,people[loc].Age < personToInsert.Age 可以按年龄排序。


虽然对于大多数列表来说,这不是最有效的排序插入方法,但对于非常小的列表(例如:少于10个元素),这可能比执行二进制搜索更快。个人而言,我会使用while而不是for(但这并不重要)。 - tigrou
这对我很有帮助,谢谢。我只需要一种简单轻便的方法来将一个新项插入到绑定到可观察集合的下拉列表的正确位置。 - Richard Moore

2

SortedList 是你需要的。创建一个 StringComparer 对象并将其传递给 sortedlist 的构造函数。新项目插入时元素会自动排序。

StringComparer stringComp = StringComparer.CurrentCulture;
SortedList sl = new SortedList(stringComp);
sl.Add("B", "SECOND");
sl.Add("A", "FIRST");
sl.Add("C", "THIRD");

2

请查看SortedSet<T>类。只需使用它,而不是List<T>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接