[Node.js]LINQを使って要素を列挙して表示する。

for文使わないで列挙する。
npm linq(linq.js)を使って、要素の表示(ダンプ)は簡単に出来ます。

ベースソース

var Enumerable = require('linq');

var a = "{\"tag\" : \"aaa\" , \"res\" : [{\"key\":\"val1\"},{\"key\":\"val2\"},{\"key\":\"val3\"}]}";
var b = "{\"tag\" : \"bbb\" , \"res\" : [{\"key\":\"val2\"},{\"key\":\"val1\"},{\"key\":\"val4\"}]}";

var json_a = JSON.parse(a);
var json_b = JSON.parse(b);
var list = json_a.res.concat( json_b.res );

連想配列listに対してLINQを実行する。

◇WriteLine()のみ

Enumerable.From(list).WriteLine();

実行結果

{ key: 'val1' }
{ key: 'val2' }
{ key: 'val3' }
{ key: 'val2' }
{ key: 'val1' }
{ key: 'val4' }

◇列挙要素の指定

Enumerable.From(list).WriteLine("$.key");

実行結果

val1
val2
val3
val2
val1
val4

◇要素を並び替えて列挙

Enumerable.From(list).OrderBy("$.key").WriteLine("$.key");

実行結果

val1
val1
val2
val2
val3
val4

[Node.js]Node.jsでLINQしてみる。

npm linqパッケージの使用。
LINQ坊なので、Node.js内でLINQ(Language Integrated Query)を使用してみたいと思います。

linq – linq.js – LINQ for JavaScript library packaged for node.js
https://github.com/mihaifm/linq
これってneue.ccさんのlinq.jsをNode.js用に移植したものだったんですねー。

ということで、linqのtutorial.jsを眺めていてもなとなくわかるのですが、本家linq.jsをダウンロードして、reference.htmを実行してみると色々サンプルが載っているので参考にしてみてください。

とりあえず、個人的によく使う、Select,Where,Take,Skip,Any,Countについてのみ。
前回のエントリーで使用したRSSフィードをJSON化したものに対して、LINQ操作をしてみたいと思います。
RSS(2.0)フィードはrss-channel-itemノードが配列になっているので、この配列をベース(From)にしてLINQ操作を行います。

ベースソース

var Enumerable = require('linq');

var request = require('request');
var url = 'http://kimux.net/?feed=rss2';

request(url, function (error, response, body) {
    if (!error && response.statusCode == 200) {
        var json = xml2json(body);
        /*
        jsonに対してLINQ操作
        */
    }
});

function xml2json(body) {
    return JSON.parse(require('xml2json').toJson(body));
}       

Select 1

        // Select - すべての記事のタイトルを列挙 ①
        console.log("\nSelect 1 - ");
        Enumerable.From(json.rss.channel.item)
            .Select("$.title")
            .WriteLine();

Selectにはイテレータ($)を使って要素にアクセスし目的のプロパティを取り出すやり方が基本形なのかな。

Select 2

        // Select - すべての記事のタイトルを列挙 ②
        console.log("\nSelect 2 - ");
        var titles = 
            Enumerable.From(json.rss.channel.item)
                .Select("$.title");
        titles.ForEach("console.log($)");

Selectの戻りは単純に要素の配列ではなくEnumerableとなっているので、継続してLINQ操作をすることができます。

Select 3

        // Select - すべての記事のタイトルを列挙 ③
        console.log("\nSelect 3 - ");
        Enumerable.From(json.rss.channel.item)
            .WriteLine("$.title");

単に表示させるだけならWriteLineに表示する要素を指定することも可能。
Select1,2,3 実行画面

Select 1 2 3 -
[Node.js]XMLをJSONに変換して操作する。
[C#]JSON.Netを使ってWebサービスから取得したJSONを扱うときのメモ。
[雑記]Nortonさんの延長画面がソレっぽく見える件。
[雑記]上原ひろみちゃんにWONDER AIRPORTに出て欲しかった。
[上原ひろみ]オフィシャル スマートフォンサイトオープン!
[雑記]Windows8は普及するのか。
[上原ひろみ]Solo@BlueNoteToKyo 2日目2nd!
[Webアプリ]nginxを使ってWebSocketのリバースプロキシを設定する。
[PC]VMware Player 5でUbuntuを手動インストールする方法。
[Webアプリ]WebSocketとGoogleMapsでリアルタイム監視マップを作る。その3。

Select 4

        // Select - すべての記事のタイトルを列挙 ④
        console.log("\nSelect 4 - ");
        Enumerable.From(json.rss.channel.item)
            .Select(function(value, index){
                return index + ":" + value.title;
            })
            .WriteLine();

indexを知ることも可。これは.Netよりも楽。
Select4 実行画面

Select 4 -
0:[Node.js]XMLをJSONに変換して操作する。
1:[C#]JSON.Netを使ってWebサービスから取得したJSONを扱うときのメモ。
2:[雑記]Nortonさんの延長画面がソレっぽく見える件。
3:[雑記]上原ひろみちゃんにWONDER AIRPORTに出て欲しかった。
4:[上原ひろみ]オフィシャル スマートフォンサイトオープン!
5:[雑記]Windows8は普及するのか。
6:[上原ひろみ]Solo@BlueNoteToKyo 2日目2nd!
7:[Webアプリ]nginxを使ってWebSocketのリバースプロキシを設定する。
8:[PC]VMware Player 5でUbuntuを手動インストールする方法。
9:[Webアプリ]WebSocketとGoogleMapsでリアルタイム監視マップを作る。その3。

Where

        // Where - タイトルに"雑記"を含む記事を表示
        console.log("\nWhere - ");
        Enumerable
            .From(json.rss.channel.item)
            .Where("$.title.indexOf('雑記') != -1")
            .Select("$.title")
            .WriteLine();

functionを使用することもできるけどイテレータを使うのが簡単で分かりやすい。
Where 実行画面

Where -
[雑記]Nortonさんの延長画面がソレっぽく見える件。
[雑記]上原ひろみちゃんにWONDER AIRPORTに出て欲しかった。
[雑記]Windows8は普及するのか。

ちなみに、次の様な書き方も出来る。

        // Where - タイトルに"雑記"を含む記事を表示
        console.log("\nWhere - ");
        Enumerable
            .From(json.rss.channel.item)
            .Where("p=>p.title.indexOf('雑記') != -1")
            .Select("$.title")
            .WriteLine();

Count

        // Count - タイトルに"雑記"を含む記事の件数
        console.log("\nCount - ");
        var cnt = 
            Enumerable
                .From(json.rss.channel.item)
                .Count("$.title.indexOf('雑記') != -1");
        console.log("Count = " + cnt);

LINQはWhereを使用しないで、Countに直接条件を書くことができます。
Count 実行画面

Count -
Count = 3

Any

        // Any - タイトルに"雑記"を含む記事の有無
        console.log("\nAny - ");
        var any = 
            Enumerable
                .From(json.rss.channel.item)
                .Where("$.title.indexOf('雑記') != -1")
                .Any();
        console.log("Any = " + any);

Any 実行画面

Any -
Any = true

Take

        // Take - 最新記事2件のタイトルを表示
        console.log("\nTake - ");
        Enumerable
            .From(json.rss.channel.item)
            .Take(2)
            .Select(function(value, index){
                return index + ":" + value.title;
            })
            .WriteLine();

Take 実行画面

Take -
0:[Node.js]XMLをJSONに変換して操作する。
1:[C#]JSON.Netを使ってWebサービスから取得したJSONを扱うときのメモ。

Skip

        // Skip - 最新記事2件目以降のタイトルを表示
        console.log("\nSkip - ");
        Enumerable
            .From(json.rss.channel.item)
            .Skip(2)
            .Select("$.title")
            .WriteLine();

Skip 実行結果

Skip -
[雑記]Nortonさんの延長画面がソレっぽく見える件。
[雑記]上原ひろみちゃんにWONDER AIRPORTに出て欲しかった。
[上原ひろみ]オフィシャル スマートフォンサイトオープン!
[雑記]Windows8は普及するのか。
[上原ひろみ]Solo@BlueNoteToKyo 2日目2nd!
[Webアプリ]nginxを使ってWebSocketのリバースプロキシを設定する。
[PC]VMware Player 5でUbuntuを手動インストールする方法。
[Webアプリ]WebSocketとGoogleMapsでリアルタイム監視マップを作る。その3。

まとめ
.NetFrameworkのLINQを知っていれば、すぐにマスターできるのでは。LINQを使えばループと条件分岐を大幅に減らすことができるのでコードが短く書けますしね。

[Node.js]XMLをJSONに変換して操作する。

RSSフィード(XML)をJSON化して操作してみる。
Node.jsでXMLをJSONに変換して読み込ませてみます。

使用環境は次の通り。
Node.js version v0.8.16
npm request   // httpリクエスト用
npm xml2json // XML->JSON変換用

RSSフィードを取得して、記事タイトルと投稿日時を表示する。
本サイトのRSSフィードをhttpリクエストで取得し、XMLをJSONに変換後、記事のタイトルと投稿日時を列挙させてみます。

RSSフィード(RSS2.0)の一部

<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">
<channel>
<title>Kimux.Net</title>
<atom:link href="http://kimux.net/?feed=rss2" rel="self" type="application/rss+xml"/>
<link>http://kimux.net</link>
<description>プログラムと趣味と。</description>
<lastBuildDate>Wed, 10 Apr 2013 01:12:51 +0000</lastBuildDate>
<language>ja</language>
<sy:updatePeriod>hourly</sy:updatePeriod>
<sy:updateFrequency>1</sy:updateFrequency>
<generator>http://wordpress.org/?v=3.5.1</generator>
<item>
<title>[C#]JSON.Netを使ってWebサービスから取得したJSONを扱うときのメモ。</title>
<link>http://kimux.net/?p=1238</link>
<comments>http://kimux.net/?p=1238#comments</comments>
<pubDate>Mon, 08 Apr 2013 08:32:35 +0000</pubDate>
<dc:creator>m-kimura</dc:creator>
<category>
<![CDATA[ C# ]]>
</category>
<category>
<![CDATA[ プログラム ]]>
</category>
<guid isPermaLink="false">http://kimux.net/?p=1238</guid>
<description>
<![CDATA[
Webサービスが提供するWebAPIからJSON形式で情報をもらう。 今やWebAPIなどの受け渡しに使うのはJSONが当たり前になっています。 そこで、C#でWebAPIなどからJSON形式の文字列を受信した時の扱いに &#8230; <a href="http://kimux.net/?p=1238">続きを読む <span class="meta-nav">&#8594;</span></a>
]]>
</description>
<content:encoded>

getRss.js

var request = require('request');
var url = 'http://kimux.net/?feed=rss2';

request(url, function (error, response, body) {
    if (!error && response.statusCode == 200) {
        var json = xml2json(body);

        for (var i in json.rss.channel.item) {
            console.log("title:" + json.rss.channel.item[i].title);
            console.log("date :" + json.rss.channel.item[i].pubDate);
        }
    }
});

function xml2json(body) {
    return JSON.parse(require('xml2json').toJson(body));
}

実行結果

$ node getRss.js
title:[C&amp;#35;]JSON.Netを使ってWebサービスから取得したJSONを扱うときのメモ。
date :Mon, 08 Apr 2013 08:32:35 +0000
title:[雑記]Nortonさんの延長画面がソレっぽく見える件。
date :Tue, 02 Apr 2013 17:04:40 +0000
title:[雑記]上原ひろみちゃんにWONDER AIRPORTに出て欲しかった。
date :Sat, 30 Mar 2013 18:59:47 +0000
title:[上原ひろみ]オフィシャル スマートフォンサイトオープン!
date :Fri, 29 Mar 2013 11:30:36 +0000
title:[雑記]Windows8は普及するのか。
date :Thu, 28 Mar 2013 06:36:38 +0000
title:[上原ひろみ]Solo@BlueNoteToKyo 2日目2nd!
date :Sat, 23 Mar 2013 16:48:40 +0000
title:[Webアプリ]nginxを使ってWebSocketのリバースプロキシを設定する。
date :Fri, 22 Mar 2013 06:21:02 +0000
title:[PC]VMware Player 5でUbuntuを手動インストールする方法。
date :Fri, 22 Mar 2013 04:27:16 +0000
title:[Webアプリ]WebSocketとGoogleMapsでリアルタイム監視マップを作る。その3。
date :Thu, 21 Mar 2013 15:30:10 +0000
title:[Webアプリ]WebSocketとGoogleMapsでリアルタイム監視マップを作る。その2。
date :Tue, 19 Mar 2013 15:09:11 +0000

XMLの属性と要素はJSONに変換するとどうなるのか。
属性値と要素が含まれるXMLをxml2jsonでJSONに変換すると、ノードの最後に要素が格納されます。

JSON変換後の一部。

{"rss":
    {
        "version":2,
        "xmlns:content":"http://purl.org/rss/1.0/modules/content/",
        "xmlns:wfw":"http://wellformedweb.org/CommentAPI/",
        "xmlns:dc":"http://purl.org/dc/elements/1.1/",
        "xmlns:atom":"http://www.w3.org/2005/Atom",
        "xmlns:sy":"http://purl.org/rss/1.0/modules/syndication/",
        "xmlns:slash":"http://purl.org/rss/1.0/modules/slash/",
        "channel":
            {"title":"Kimux.Net","atom:link":{"href":"http://kimux.net/?feed=rss2","rel":"self","type":"application/rss+xml"},"link":"http://kimux.net","description":"プログラムと趣味と。","lastBuildDate":"Wed, 10 Apr 2013 01:12:51 +0000","language":"ja","sy:updatePeriod":"hourly","sy:updateFrequency":1,"generator":"http://wordpress.org/?v=3.5.1",
    

XMLパースが面倒だったので、なんかJSONにしたら楽なのかなぁって思ったから、ちょっと試してみたけど、マジ楽だったw