【问题标题】:Algorithm for sorting a list of objects in c#c#中对对象列表进行排序的算法
【发布时间】:2009-05-15 06:01:00
【问题描述】:

我有一个要在 C#.Net 3.5 中排序的对象列表,对象如下

标识 |姓名 | parent_id

1 |超人 |空

2 |蝙蝠侠 | 3

3 |守望者 | 1

4 |金刚狼 | 2

我知道你们中的一些人可能会觉得这很容易,但我需要根据 parent_id 对列表进行排序,它指向同一张表中自己的索引(id)。

那么有人可以给我一个很好的算法来对这个列表进行排序而不会一遍又一遍地循环吗?我真的不能说得那么好,因此我似乎无法在谷歌上搜索到我想要的正确结果。

IEnumerable 或 DataTable 解决方案的集合会很棒。

提前致谢。

编辑:----------------新示例

标识 |姓名 | parent_id

1 |顶级儿童 |空

2 |孩子 C | 3

3 |孩子 B | 4

4 |孩子A | 1

----> 我想要的输出是

标识 |姓名 | parent_id

1 |顶级儿童 |空

4 |孩子A | 1

3 |孩子 B | 4

2 |孩子 C | 3

---->如果我使用OrderBy或Sort,我得到的结果是

标识 |姓名 | parent_id

1 |顶级儿童 |空

4 |孩子A | 1

2 |孩子 C | 3

3 |孩子 B | 4

--> 没有一个解决方案是我真正想要的, 再次抱歉没有说清楚

希望这个例子更清楚

【问题讨论】:

  • 我不知道任何 C#,但我确信 C# 中有一种叫做“比较器函数/对象”的东西。 C# 应该有某种用于排序的库函数。只需传入您的集合和比较器函数,它应该能够为您排序集合。
  • 我不是 100% 清楚所需的顺序 - “基于 parent_id,它指向同一张表中自己的索引(id)”是什么意思?也许显示所需的输出?
  • 编辑后更不清晰了。需要按什么顺序排序。对我来说,1、3、4 是父 ID 的正确排序顺序,而不是 1、4、3
  • 不是按序号,而是按父级。 Child A 的 parent_id 为 1(Parent A),Child B 的 parent id 为 4(Child A),Child C 的 parent_id 为 3(Child B),因此应该按顺序显示 child A、B、C
  • 我想我明白你在找什么。检查我修改后的比较器。

标签: c# .net algorithm


【解决方案1】:

编辑后:我想我明白了,比较器看起来像:

public Int32 CompareTo(SuperHero right)
{
    if (this.ID == right.ID)
        return 0;

    return this.ParentID.CompareTo(right.ID);
}

回应您的评论:

类看起来像:

public class SuperHero : IComparable<SuperHero>
{
    public Int32 ID { get; set; }
    public String Name { get; set; }
    public Int32 ParentID { get; set; }

    public SuperHero(Int32 id, String name, Int32 pid)
    {
        this.ID = id;
        this.Name = name;
        this.ParentID = pid;
    }

    public Int32 CompareTo(SuperHero right)
    {
        if (this.ID == right.ID)
            return 0;

        return this.ParentID.CompareTo(right.ID);
    }

    public override string ToString()
    {
        return this.Name;
    }
}

并使用它:

static void Main(string[] args)
{
    // create your list
    List<SuperHero> heroes = new List<SuperHero>();

    // populate it
    heroes.Add(new SuperHero(1, "Superman", 0));
    heroes.Add(new SuperHero(2, "Batman", 3));
    heroes.Add(new SuperHero(3, "Watchman", 1));
    heroes.Add(new SuperHero(4, "Wolverine", 2));

    foreach (SuperHero hero in heroes)
        Console.WriteLine(hero.ToString());
    Console.WriteLine();

    // sort it
    heroes.Sort();

    foreach (SuperHero hero in heroes)
        Console.WriteLine(hero.ToString());

    Console.ReadKey();
}

.NET 排序 (QuickSort) 将使用您的比较器对列表进行排序。

【讨论】:

  • 如何使用 CompareTo() 对列表进行排序?
  • 谢谢,虽然它没有按我想要的 100% 工作,但我想你已经为我指明了正确的方向......再次感谢
【解决方案2】:

可以为以上数据创建一个类,以id、name、parent_id为类成员。 重写 IComparable 的 CompareTo 方法

    public class Person : IComparable<Person>
        {
            public int id, parentID;
            public string name;

            public Person(int id, string name, int parentID)
            {
                this.id = id;
                this.name = name;
                this.parentID = parentID;
            }

            #region IComparable Members

            public int CompareTo(Person obj)
        {
        return this.parentID.CompareTo(obj.parentID);

        //OR 
        //if (this.parentID > obj.parentID)
        //{
        //    return 1;
        //}
        //else if (this.parentID < obj.parentID)
        //{
        //    return -1;
        //}

        //return 0;
        }        
            #endregion
        }

在主代码中:

List<Person> peopleArray = new List<Person>();
            peopleArray.Add(new Person(1, "Jerry", 1));
        peopleArray.Add(new Person(2, "George", 4));
        peopleArray.Add(new Person(3, "Elaine", 3));
        peopleArray.Add(new Person(4, "Kramer", 2));    
            peopleArray.Sort();

            foreach (Person p in peopleArray)
                Console.WriteLine(p.parentID);

这将按父 ID 对列表进行排序 父 ID 的 O/P: 1 2 3 4

【讨论】:

  • 我不确定 OP 如何表示 parentId 的 NULL 值。也许你需要考虑一下。
  • 在已经实现 IComparable 的字段上进行比较时,返回其 Compare 方法的结果比返回 -1、1 和 0 更好。例如,比较两个整数会返回它们的差异。这可以优化比较。比如:返回 this.parentID.CompareTo(((Person)obj).parentID)
  • 虽然在 Int32 的情况下,只返回 this.parentID - ((Person)obj).parentID 可能会更快。
  • shahKalpesh -- int 在我的情况下不是 Nullable,默认值为 0
  • @Josh - 也使用通用 IComparable(T) 来避免类型转换。
【解决方案3】:

简单的方法:

using System.Linq;
...
var sorted = unsorted.OrderBy(x=>x.parent_id);

更复杂/可重用的方式:

在 .NET 中,您只需替换一种方法即可使用现有的排序工具(如 Array.Sort、List.Sort、LINQ 的 OrderBy 等)。您需要实现一个比较器(通过创建实现 IComparer 的对象、在被比较的对象上实现 IComparable 或使用比较委托。)

比较器的所有工作就是确定给定对象是否大于或小于另一个对象。只要您这样做并遵循一些基本规则(即,如果 X 大于 Y,则 Y 必须小于 X),那么排序将快速而轻松。

【讨论】:

    【解决方案4】:

    如果在对象中实现 IComparable,则可以对 Array 或 ArrayList 集合使用 .Sort 方法。

    【讨论】:

      【解决方案5】:

      我猜你希望 NULL parentId 是第一个,然后是它的孩子。
      如果是这样,您可以使用 linq 在列表中调用 OrderBy。

      OrderBy(x => Convert.ToInt32(x.ParentId == null ? "0" : x.ParentId));

      我假设 ParentId 是一个字符串(如果它是 int 则不能为 null)。
      并假设该列表不会有 Id = 0。

      编辑:这将按以下顺序打印项目
      超人
      守望者
      金刚狼
      蝙蝠侠

      【讨论】:

        猜你喜欢
        • 2016-11-03
        • 2010-10-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-01
        • 2013-05-06
        • 1970-01-01
        相关资源
        最近更新 更多