Сортировка списка по иерархии - PullRequest
0 голосов
/ 04 ноября 2011

мне нужно отсортировать список по иерархии, кто-нибудь может мне помочь?Список выглядит так:

        // 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
  • дедушка
  • отец
  • child

Я пытался реализовать IComparable в моем классе "Person", например:

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 ]

5 голосов
/ 04 ноября 2011

Вам необходимо вычислить отдел элементов в иерархии и отсортировать список по отделу:

Если следующий класс лица:

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

Затем метод можно использовать для сортировки списка по dept

.
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) поиск в списке. Все это может быть улучшено путем вычисления dept только один раз для каждого человека и его хранения в сочетании с более эффективным механизмом поиска, таким как словарь, для обеспечения хорошей производительности для больших наборов данных.

1 голос
/ 04 ноября 2011

Ваша проблема в том, что у вас нет способа определить, что больше, если значения разбросаны слишком далеко друг от друга.Например: ваш дед и дочерние элементы всегда будут возвращать -1, поскольку строка «папа» всегда меньше строки «дед».Попробуйте преобразовать ваши личные значения в постоянные значения типа 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;
    }
}
0 голосов
/ 04 ноября 2011

Это проблема с данными.Вы пытаетесь сравнить строковые значения, но в ваших данных нет ничего, что обеспечивало бы относительные связи.

Я бы посоветовал вам преобразовать ваши значения в 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);
    }

}
0 голосов
/ 04 ноября 2011

Вы должны изменить логику вашего 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 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...