【问题标题】:Alphabetically sort a generic list of objects using a specified property使用指定属性按字母顺序对对象的通用列表进行排序
【发布时间】:2012-03-21 11:34:23
【问题描述】:

我正在编写一个地址簿程序。我将每个人的详细信息存储在List<Person> 中。我需要能够按姓氏(如果有联系,则使用名字)或邮政编码对这个列表进行排序。

到目前为止,我有这个:

public class Person
{
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string PostCode { get; set; }
    // etc..
}

public class AddressBook
{
    public List<Person> People { get; set; }

    // asc: ascending or descending
    // column: the property to use when sorting
    //         (in my case either LastName or Postcode)
    public void Sort(bool asc, string column)
    {
        // What should I put here?
    }

    // etc...
}

我尝试过使用ICompareIComparable 接口,但我就是不明白。

Sort方法怎么写?

【问题讨论】:

  • 您使用的是什么版本的 C# / .NET?
  • 我试图清理你的问题,以便更容易阅读。希望没事。

标签: c# sorting generic-list


【解决方案1】:

假设:

 List<Person> personList;

然后使用 Linq:

 IEnumerable<Person> orderedByLastName = personList.OrderBy(p => p.LastName)

【讨论】:

  • 感谢 Spender,我显然遗漏了一些东西(需要对 linq 做更多的阅读),因为这根本不适合我。当我通过 sort 方法运行测试时,List 根本没有排序。
  • @user1243505:那是因为这个 - 以及马克的回答 - 不要进行就地排序。它们返回一个 new 对象,其中包含按排序顺序排列的原始列表的内容。
【解决方案2】:

您可以尝试使用 LINQ 扩展方法OrderByOrderByDescendingThenByThenByDescending

using System.Linq;

// ...

public void Sort(bool asc, string column)
{
    switch (column)
    {
        case "LastName":
            People = People.OrderBy(x => x.LastName).ThenBy(x => x.FirstName).ToList();
            break;
        case "PostCode":
            People = People.OrderBy(x => x.PostCode).ToList();
            break;
        default:
            // error handling
    }

    if (!asc)
    {
        People.Reverse();
    }
}

您还可以查看可以简化此代码的 Dynamic LINQ。

【讨论】:

  • 感谢您的回复。正如我在下面所说,我需要更多地研究 linq,因为我不明白如何让你的代码对列表进行排序。不过感谢您的帮助。
  • @user1243505:如果我是你,我会投资我的未来并学习 LINQ。它更简单,更易于使用。从长远来看,现在对自己的教育进行少量投资将为您节省大量时间,并使您将来成为更有价值的程序员。但这是你的生活、事业、选择……
【解决方案3】:

你可以使用IComparer&lt;T&gt;的实现:

public class PersonComparer : IComparer<Person>
{
    private readonly bool _sortAscending;
    private readonly string _columnToSortOn;

    public PersonComparer(bool sortAscending, string columnToSortOn)
    {
        _sortAscending = sortAscending;
        _columnToSortOn = columnToSortOn;
    }

    public int Compare(Person x, Person y)
    {
        if(x == null && y == null) return 0;
        if(x == null) return ApplySortDirection(-1);
        if(y == null) return ApplySortDirection(1);

        switch(_columnToSortOn)
        {
            case "LastName":
                return ApplySortDirection(SortByName(x, y));
                break;
            case "PostCode":
                return ApplySortDirection(SortByPostCode(x, y));
                break;
            default:
                throw new ArgumentOutOfRangeException(
                    string.Format("Can't sort on column {0}",
                    _columnToSortOn));
        }
    }

    private int SortByPostCode(Person x, Person y)
    {
        return x.PostCode.CompareTo(y.PostCode);
    }

    private int SortByName(Person x, Person y)
    {
        var lastNameResult = x.LastName.CompareTo(y.LastName);
        if(lastNameResult != 0)
            return lastNameResult;
        return x.FirstName.CompareTo(y.FirstName);
    }

    private int ApplySortDirection(int result)
    {
        return _sortAscending ? result : (result * -1);
    }
}

您可以像这样在AddressBook 类的Sort 方法中使用它,假设PeopleList&lt;Person&gt;

public void Sort(bool asc, string column)
{
    People.Sort(new PersonComparer(asc, column));
}

此代码具有使用就地排序的好处。

【讨论】:

  • 完美运行。并且...(更好)我明白了...非常感谢!
  • @user1243505:不客气。请不要忘记接受我的回答:How to accept an answer?
猜你喜欢
  • 2018-04-19
  • 1970-01-01
  • 1970-01-01
  • 2021-05-10
  • 1970-01-01
  • 1970-01-01
  • 2021-03-20
  • 1970-01-01
相关资源
最近更新 更多