Самый эффективный способ узнать элемент списка (или коллекции) о родительском списке? - PullRequest
1 голос
/ 30 декабря 2011

Часто со списками и элементами внутри них я нахожу необходимость запрашивать или находить в списке объекты, к которым был добавлен объект.

Например:

// create list of levels
IList<Levels> levels = new List<Levels>
{
    levels.Add(new Level{ Depth = 1, Name = "Level 1" });
    levels.Add(new Level{ Depth = 2, Name = "Level 2" });
}

foreach(Level level in levels)
{
    bool lowestLevel = false;

    // would the lowest level be best worked out from a function that takes the list and the level?
    lowestLevel = Level.GetLowest(Levels, level);

    // as a calculated property of level itself where the level knows about the list of levels it's in?
    lowestLevel = Level.IsLowest;

    // or worked out when creating the level?
    // levels.Add(new Level{ Depth = 1, Name = "Level 1", IsLowest = isLowest });
    lowestLevel = Level.IsLowest;
}

Является ли какой-либо из этих методов «наилучшей практикой», чтобы справиться с чем-то подобным или есть другой способ?

Заранее спасибо.

Ответы [ 4 ]

2 голосов
/ 30 декабря 2011

Игнорирование того факта, что добавление в коллекцию, которая повторяется, вызывает исключение ...

Определенно есть другой путь. Когда Level нужно знать о его братьях и сестрах, вы должны инкапсулировать levels внутри класса, скажем, LevelCollection. Вы можете дать каждому Level ссылку на его родительскую коллекцию, когда вставляете уровень в коллекцию и прекращаете передачу levels в методы, которые требуют родственных элементов.

1 голос
/ 30 декабря 2011

Зачем теперь использовать Linq:

lowest = list.Max(x => x.Level);
highest = list.Min(x => x.Level);

Обратите внимание, что некоторые методы Linq недоступны, если ваш список имеет тип IList. Также, если вы хотите получить реальный объект (уровень), вы должны использовать что-то вроде:

var lowest = list.OrderBy(x => x.Level).First();
0 голосов
/ 30 декабря 2011

Не сохраняйте Depth для типа Level. Вместо этого передайте ссылку на коллекцию. Level.Parent = this; в вашем List.Add методе. Вы всегда можете получить глубину по List.IndexOf (Level). Таким образом, вам не нужно будет обновлять глубину для всех участников каждый раз, когда вы меняете коллекцию.

public class Level
{
    public IList<Level> Parent { get; set; }

    public string Name { get; set; }
}

public class LevelCollection : Collection<Level>
{
    protected override void InsertItem(int index, Level item)
    {
        base.InsertItem(index, item);
        item.Parent = this;
    }

    protected override void RemoveItem(int index)
    {
        this[index].Parent = null;
        base.RemoveItem(index);
    }
}

Тогда вы можете просто запросить у родителя глубину предмета внутри уровня.

this.Parent.IndexOf(this);
0 голосов
/ 30 декабря 2011

Лучшей практикой является выбор правильной структуры для правильной задачи.Список очень распространенная структура и не имеет каких-либо специальных функций.

Так что для этого случая у вас должна быть какая-то структура, где, когда вы добавляете элемент, он должен решить, куда его поместить.Вся теория графов будет очень полезна для вас, чтобы выбрать правильное решение.Если вы найдете такую ​​структуру, то вам нужно проверить, что уже реализовано..NET Framework содержит много общей структуры, которая может быть полезна.

Таким образом, вместо List вы можете использовать SortedList , и ваш класс Level должен реализовывать интерфейс IDictionary .

Каждый раз, когда вы добавляете экземпляр уровня в такой список, самый низкий уровень будет находиться под индексом 0 таблицы (или размером -1, это зависит от IComparable , который вы будете использовать)

Хорошая статья о Структура данных в C # 2.0

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...