Класс C# TreeNode, который может конвертировать из списка.C#

Место общения программистов C#
Ответить
Anonymous
 Класс C# TreeNode, который может конвертировать из списка.

Сообщение Anonymous »

Сегодня утром у меня возникла очень необычная проблема: мне пришлось создать дерево сочетаний клавиш. Это потребовало удобного способа преобразования списка в дерево, и поэтому я придумал следующий класс TreeItem, который работает просто великолепно.
Я решил, что этим стоит поделиться с сообществом, не как модель того, как это следует делать, поскольку такой вещи не существует, а, возможно, чтобы пробудить немного творчества. Конструктивная критика, как всегда, приветствуется!
public class TreeNode : IEnumerable
where T : class
{
public static TreeNode FromList(IEnumerable list, Func keysSelector, Func itemSelector)
{
return new TreeNode(null, GetRootChildren().ToArray());

IEnumerable GetRootChildren()
{
var uniqueKeysList = new List { };

foreach (var listItem in list)
{
var keys = keysSelector(listItem);
var topKey = keys.First();

if (uniqueKeysList.Contains(topKey))
continue;

uniqueKeysList.Add(topKey);

var item = itemSelector(listItem, topKey, 0);
var children = GetChildren(new[] { topKey }, 1).ToArray();
yield return new TreeNode(item, children);
}
}

IEnumerable GetChildren(TKey[] recursionParentKeys, int recursionLevel)
{
foreach (var listItem in list)
{
var keys = keysSelector(listItem);
var bottommostRecursionLevel = keys.Count() - 1;

if (recursionLevel > bottommostRecursionLevel)
continue;

var parentKeys = keys.Take(recursionLevel);

if (recursionParentKeys.SequenceEqual(parentKeys))
yield return CreateChild();

TreeNode CreateChild()
{
var recursionLevelKey = keys.ElementAt(recursionLevel);
var item = itemSelector(listItem, recursionLevelKey, recursionLevel);
return new TreeNode(item, GetChildren(recursionParentKeys.Append(recursionLevelKey).ToArray(), recursionLevel + 1).ToArray());
}
}
}
}

public TreeNode(T item, params TreeNode[] children)
{
Item = item;
this.children = children.ToList();
}

public void AddChild(TreeNode child)
{
children.Add(child);
child.Parent = this;
}

public void RemoveChild(TreeNode child)
{
children.Remove(child);
child.Parent = null;
}

public T Item { get; }

public TreeNode Parent { get; protected set; } = null;

public ReadOnlyCollection Children => children.AsReadOnly();

private List children { get; }

public IEnumerator GetEnumerator() => Children.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => Children.GetEnumerator();
}

Вот пример, основанный на моем конкретном сценарии использования:
var chordCommandDictionary = new Dictionary
{
{ new KeysChord { Keys.Control | Keys.A, Keys.Control | Keys.C }, Commands.Command1 },
{ new KeysChord { Keys.Control | Keys.A, Keys.Control | Keys.D }, Commands.Command2 },
{ new KeysChord { Keys.Control | Keys.A, Keys.Control | Keys.E }, Commands.Command3 },
{ new KeysChord { Keys.Control | Keys.B, Keys.Control | Keys.C }, Commands.Command4 },
{ new KeysChord { Keys.Control | Keys.B, Keys.Control | Keys.D }, Commands.Command5 },
{ new KeysChord { Keys.Control | Keys.B, Keys.Control | Keys.E }, Commands.Command6 },
{ new KeysChord { Keys.Control | Keys.B, Keys.Control | Keys.E, Keys.Control | Keys.F }, Commands.Command6 },
};

var tree = TreeNode.FromList(
ChordCommandDictionary,
from => from.Key.Keys,
(from, key, recursionLevel) => new KeysChordStep(key, recursionLevel == from.Key.Keys.Count - 1 ? from.Value : null));


Подробнее здесь: https://stackoverflow.com/questions/792 ... rom-a-list
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»