2008年02月04日

Linq to XML その10

   このエントリーをはてなブックマークに追加 Clip to Evernote
たぶん最終回。

もう一度、利用するXMLを載せておきます。

<?xml version="1.0" encoding="utf-8"?>
<People>
<Person IsReal="true">
<Name>坂本竜馬</Name>
<Age>35</Age>
</Person>
<Person IsReal="true">
<Name>井伊直弼</Name>
<Age>44</Age>
</Person>
<Person IsReal="false">
<Name>明智小五郎</Name>
<Age>39</Age>
</Person>
<Person IsReal="true">
<Name>勝海舟</Name>
<Age>18</Age>
</Person>
<Person IsReal="true">
<Name>西郷隆盛</Name>
<Age>52</Age>
</Person>
<Person IsReal="false">
<Name>両津勘吉</Name>
<Age>40</Age>
</Person>
</People>


このXMLを読み込んで、実在の人物の平均年齢を求めたいとします。
どんなコードを書けばよいのでしょうか?

すぐに思いつくのが、こんなコードかな。

XDocument xdoc = XDocument.Load("people.xml");
double sum = 0;
int count = 0;
foreach (var xperson in xdoc.Root.Elements()) {
bool isReal = (bool?)xperson.Attribute("IsReal") ?? true;
if (isReal) {
sum += (int)xperson.Element("Age");
count++;
}
}
Console.WriteLine(sum / count);


でも、これだと、Linq to XMLの機能を十分に使っていません。

Averageメソッドを使って、こんな風にかけます。

 var query = from xperson in xdoc.Root.Elements()
where (bool?)xperson.Attribute("IsReal") ?? true == true
select (int)xperson.Element("Age");
Console.WriteLine(query.Average());


もうひとつのやり方。

var grp = from xperson in xdoc.Root.Elements()
where (bool)xperson.Attribute("IsReal") == true
group xperson by (bool)xperson.Attribute("IsReal") into g
select new { IsReal = g.Key, Average = g.Average(p => (int)p.Element("Age")) };
foreach (var g in grp) {
Console.WriteLine(g.IsReal);
Console.WriteLine(g.Average);
}
Console.WriteLine(grp.First().Average);


これだと、要求を正しく実装していませんが、平均を求めることができています。

もっと良い方法があるかもしれないけど、思いつきません。



バックナンバー
Linq to XML その1
Linq to XML その2
Linq to XML その3
Linq to XML その4
Linq to XML その5
Linq to XML その6
Linq to XML その7
Linq to XML その8
Linq to XML その9

Linq to XML その11
Linq to XML その12


 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/51385743