RSS

日別アーカイブ: 2013/12/05

Advent LINQ (5): Flatten

Advent LINQ (3)で、フォルダを探索しながらファイルを列挙するFilesAsEnumerableを作った。このような、木構造のシーケンスを探索するというシチュエーションは、色々ありそうだ。なので、このアルゴリズムを一般化する事を考える。

public static class LinqExtensions
{
	public static IEnumerable<U> Flatten<T, U>(
		this T node,
		Func<T, IEnumerable<T>> predictBySubNode,
		Func<T, IEnumerable<U>> predictByNode)
	{
		var bySubNode =
			from subNode in predictBySubNode(node)
			from childNode in Flatten(subNode, predictBySubNode, predictByNode)
			select childNode;

		var byNode =
			from childNode in predictByNode(node)
			select childNode;

		return bySubNode.Concat(byNode);
	}
}

これを使ってファイルの探索を行うには、以下のように記述する。

var baseDirectory = new DirectoryInfo(@"C:\project");
foreach (var file in baseDirectory.Flatten(
	directory => directory.GetDirectories(),
	directory => directory.GetFiles("*.cs")))
{
	Console.WriteLine(file.FullName);
}

XmlDocumentから、テキストノードを抜き出してみる。

var document = new XmlDocument();
document.Load(@"C:\project\data.xml");
foreach (var text in document.DocumentElement.Flatten(
	element => element.SelectNodes("*").Cast<XmlElement>(),
	element => element.SelectNodes("text()").Cast<XmlText>()))
{
	Console.WriteLine(text.Value);
}

もちろん、XDocumentにも応用可能。

広告
 
コメントする

投稿者: : 2013/12/05 投稿先 .NET, LINQ

 
 
%d人のブロガーが「いいね」をつけました。