按层次排序列表

时间:2011-11-04 18:31:30

标签: c# list sorting

我需要按层次排序列表,有人可以帮忙吗?该列表如下所示:

        // create your list
        List<Person> persons = new List<Person>();

        // populate it
        persons.Add(new Person("child", "father"));
        persons.Add(new Person("father", "grandfather"));
        persons.Add(new Person("grandfather", "grandgrandfather"));
        persons.Add(new Person("grandgrandfather", null));

我想要类似的东西:

  • grandgrandfather
  • 祖父
  • 父亲

我尝试在我的classe“Person”中实现IComparable,如下所示:

public class Person : IComparable<Person>
{
    public String ID { get; set; }
    public String ParentID { get; set; }

    public Person(String id, String pid)
    {
        this.ID = id;
        this.ParentID = pid;
    }

    public Int32 CompareTo(Person right)
    {


        if (this.ID.Equals(right.ID))
            return 0;

        if (this.ParentID == null) return -1;
        if (right.ParentID == null) return 1;


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

}

但它没有做到这一点...

4 个答案:

答案 0 :(得分:5)

您需要计算层次结构中项目的部门,并按部门对列表进行排序:

如果以下是人员类:

class Person 
{
    public string Name {get; private set;}
    public string Parent {get; private set;}

    public Person(string name, string parent) 
    {
        this.Name = name;
        this.Parent = parent;
    }
}

这是计算层次结构中人员的部门的方法示例。

int GetDept(List<Person> list, Person person) 
{
    if (person.Parent == null) return 0;
    return GetDept(list, list.First(p => p.Name == person.Parent)) + 1;
}

然后该方法可用于按部门

对列表进行排序
List<Person> persons = new List<Person>();

// populate it
persons.Add(new Person("child", "father"));
persons.Add(new Person("father", "grandfather"));
persons.Add(new Person("grandfather", "grandgrandfather"));
persons.Add(new Person("grandgrandfather", null));

var sorted = persons.OrderBy(p => GetDept(persons, p));

foreach(var person in sorded)
    Console.WriteLine("{0} {1} {2}", person.Name, person.Parent, GetDept(persons, p))

这将打印:

grandgrandfather null                0
grandfather      grandgrandfather    1
father           grandfather         2
child            father              3

请注意,在此示例中,dept不能有效计算,因为GetDept方法将一次又一次地调用它,并且它还使用O(n)查找列表。所有这些都可以通过为每个人计算部门一次并存储它来改进,结合更高效的查找机制(如字典),以便获得大数据集的良好性能。

答案 1 :(得分:1)

您的问题是,如果值分散得太远,您无法确定哪个更大。例如:您的祖父和子元素将始终返回-1,因为字符串“father”始终小于字符串“grandfather”。尝试将您的人值设为常数int值,然后比较如下:

const int child = 0;
const int father = 1;
const int grandfather = 2;
const int greatgrandfather = 3;

// create your list
List<Person> persons = new List<Person>();

// populate it
persons.Add(new Person(child));
persons.Add(new Person(father));
persons.Add(new Person(grandfather));
persons.Add(new Person(grandgrandfather));

public class Person : IComparable<Person>
{
    public int ID { get; set; }

    public Person(int id)
    {
        this.ID = id;
    }

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

        if (this.ID > right.ID) return -1;
        else return 1;
    }
}

答案 2 :(得分:0)

您必须根据排序逻辑修改public int CompareTo(Person right)方法的逻辑。

例如

if (this.ID == grandgrandfather &&  
        right.ID == grandfather) return 1;


if (this.ID == grandgrandfather &&  
        right.ID == child) return 1;

....... a lot more 

答案 3 :(得分:0)

这是一个数据问题。您正在尝试比较字符串值,但您的数据中没有固有的东西可以提供相对关系。

我建议您将值转换为Enum,然后可以轻松比较。这是一些我没有测试过的伪代码,但它应该给你一个想法:

public class Person : IComparable<Person>
{
        public enum Types: int {
            None,
            Child,
            Father,
            Grandfather,
            GrandGrandFather
        }
    public Types ID { get; set; }
    public Types ParentID { get; set; }

    public Person(Types id, Types pid)
    {
        this.ID = id;
        this.ParentID = pid;
    }

    public Int32 CompareTo(Person right)
    {
        return this.ParentID.CompareTo(right.ID);
    }

}