Last active
August 29, 2015 14:14
-
-
Save createdbyx/a58a826777421d90a86b to your computer and use it in GitHub Desktop.
Constructs a nested hierarchy of types from a flat list of source types. (without recursive calling)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Sample use case ... | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var paths = new[] | |
{ | |
"assets/folder", | |
"assets/folder/filea.txt", | |
"assets/folder/fileb.txt", | |
"assets/folderb", | |
"assets/folderb/filex.txt", | |
"assets/folderb/filey.txt", | |
}; | |
var separator = new[] { Path.AltDirectorySeparatorChar.ToString(CultureInfo.InvariantCulture) }; | |
var nodes = paths.ToHierarchy( | |
x => x.Split(separator, StringSplitOptions.RemoveEmptyEntries), | |
(r, p) => string.CompareOrdinal(r.Name, p) == 0, | |
r => r.Nodes, | |
(r, c) => ((List<TreeViewNode>)r).Add(c), | |
CreateTreeNode); | |
foreach (var node in nodes) | |
{ | |
WriteNode(node); | |
} | |
//outputs | |
//---------- | |
//assets - assets | |
// folder - assets\folder | |
// filea.txt - assets\folder\filea.txt | |
// fileb.txt - assets\folder\fileb.txt | |
// folderb - assets\folderb | |
// filex.txt - assets\folderb\filex.txt | |
// filey.txt - assets\folderb\filey.txt | |
Console.ReadKey(); | |
} | |
private static TreeViewNode CreateTreeNode(string[] parts, int index, string source) | |
{ | |
var node = new TreeViewNode() { Name = parts[index] }; | |
node.Value = string.Join(Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture), parts, 0, index + 1); | |
if (index == parts.Length - 1) | |
{ | |
node.Name = Path.GetFileName(source); | |
} | |
return node; | |
} | |
public static void WriteNode(TreeViewNode node, int depth = 0) | |
{ | |
Console.WriteLine("{0}{1} - {2}", new String(' ', depth), node.Name, node.Value); | |
foreach (var child in node.Nodes) | |
{ | |
WriteNode(child, depth + 2); | |
} | |
} | |
} | |
public class TreeViewNode | |
{ | |
public List<TreeViewNode> Nodes { get; set; } | |
public TreeViewNode() | |
{ | |
this.Nodes = new List<TreeViewNode>(); | |
this.IsExpanded = true; | |
} | |
public string Value { get; set; } | |
public string Name { get; set; } | |
public bool IsExpanded { get; set; } | |
public bool IsChecked { get; set; } | |
} | |
*/ | |
public static class ExtensionMethods | |
{ | |
/// <summary> | |
/// Constructs a nested hierarchy of types from a flat list of source types. | |
/// </summary> | |
/// <typeparam name="TSource">The source type of the flat list that is to be converted.</typeparam> | |
/// <typeparam name="TReturn">The type that will be returned.</typeparam> | |
/// <typeparam name="TPart">The type of the art type.</typeparam> | |
/// <param name="sourceItems">The source items to be converted.</param> | |
/// <param name="getParts">A callback function that returns a array of <see cref="TPart"/>.</param> | |
/// <param name="comparePart">The compare part callback.</param> | |
/// <param name="getChildren">The get children callback.</param> | |
/// <param name="addChild">The add child callback.</param> | |
/// <param name="createItem">The create item callback.</param> | |
/// <returns>Returns an collection of <see cref="TReturn"/> representing the hierarchy.</returns> | |
/// <exception cref="Exception">A delegate callback throws an exception. </exception> | |
public static IEnumerable<TReturn> ToHierarchy<TSource, TReturn, TPart>( | |
this IEnumerable<TSource> sourceItems, | |
Func<TSource, TPart[]> getParts, | |
Func<TReturn, TPart, bool> comparePart, | |
Func<TReturn, IEnumerable<TReturn>> getChildren, | |
Action<IEnumerable<TReturn>, TReturn> addChild, | |
Func<TPart[], int, TSource, TReturn> createItem) | |
{ | |
var treeModels = new List<TReturn>(); | |
foreach (var keyName in sourceItems) | |
{ | |
IEnumerable<TReturn> items = treeModels; | |
var parts = getParts(keyName); | |
for (var partIndex = 0; partIndex < parts.Length; partIndex++) | |
{ | |
var node = items.FirstOrDefault(x => comparePart(x, parts[partIndex])); | |
if (node != null) | |
{ | |
items = getChildren(node); | |
continue; | |
} | |
var model = createItem(parts, partIndex, keyName); | |
addChild(items, model); | |
items = getChildren(model); | |
} | |
} | |
return treeModels; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment