JavaScriptで配列をコピーする

JavaScriptで配列をコピーするときは次のような注意が必要です。

a=[10,20,30];
b=a;

配列変数aを配列変数bにコピーしています。
これで配列変数bをaの代わりに使うことができます。

次にpopを使ってaの最後の要素をクリアします。

a.pop();

この場合、bには何も影響しないように思われますが、実行結果は次のようになります。

a=[10,20]
b=[10,20]

bもaと同じく最後の要素がクリアされます。
つまり「b=a」とすると各要素がコピーされるのではなく「bはaを参照する」ということになるのです。
したがって各要素をコピーするためには次のようにします。

a=[10,20,30];
for(i=0;i<a.length;i++){
  b[i]=a[i];
}
a.pop();

実行結果は次の通り。

a=[10,20]
b=[10,20,30]

意図通り、aだけが処理されました。

なお次のような簡単な方法もあります。
sliceを使うと配列を部分的に抜き出すことができます。
第1引数にセットした位置から第2引数にセットした位置の前まで抜き出します。
第1引数に「0」をセットし、第2引数を省略すると、最初から最後までを抜き出しますので、配列の各要素をコピーするのと同じ効果があります。

a=[10,20,30];
b=a.slice(0);
a.pop();

switchとifで速いのはどっち?(JavaScript)

前に、VBAで「SelectCaseとIfで速いのはどっち?」というのを調べてみましたが、今度はJavaScriptで同じことをしてみました。なお、SelectCaseはswitchに置き換えます。
サンプルコードは省略しますが、同様の関数を作り、10000回繰り返したときの実行時間を測りました。

サンプル 時間
配列変数 0.5124秒
switch 0.0688秒
if(単純) 0.2594秒
if(終了) 0.0359秒
if(場合分け) 0.0359秒

面白いのはifの場合分けを使った場合の効果に違いが見られなかったことです。

東日本大地震からの経過年月日を表示する

東日本大地震が起きたのが3月11日。
ちょうど3か月が経過しました。
これを自動的にカウントするJavaScriptのコードを書いてみました。

document.write(count_ymd());
function count_ymd() {
    var fdy = 2011,
        fdm = 3 - 1,
        fdd = 11;
    var td = new Date();
    var tdy = td.getFullYear(),
        tdm = td.getMonth(),
        tdd = td.getDate();
    var dy = tdy - fdy;
    var dm = tdm - fdm;
    var dd = tdd - fdd;
    if (dd < 0) {
        dd = (new Date(tdy, tdm, 0)).getDate() - fdd + tdd;
        dm--;
    }
    if (dm < 0) {
        dm = dm + 12;
        dy = dy - 1;
    }
    return ((dy > 0 ? dy + "年" : "") + (dm + "か月") + (dd > 0 ? dd + "日" : "ちょうど"));
}

「同じ文字が2個並んだ文字列」の正規表現

「book」の「oo」のように文字の繰り返しを見付ける正規表現について調べました。

JavaScriptの場合

まず/.{2}/という表現を思い付きますが、これでは「同じ文字が2個並んだ文字列」になりません。単に「文字が2個並んだ文字列」です。1個目と2個目の文字が異なってもよいからです。
そこで次のようにします。

str="book";
ret=str.match(/(.)\1/g);

「oo」が返されます(正確にはret[0]として)。
JavaScriptの正規表現では「\1」を使うと括弧に挟まれた部分を取得できます。
/(.)/とすると任意の1文字が取得でき、\1に格納されます。
/(.)\1/とすると/\1\1/のように「同じ文字が2個並んだ文字列」を探すことになります。

秀丸の場合

検索文字列として「(.)\1」を指定します。
もちろん正規表現にチェックを入れます。
もし「同じ文字が2個以上並んだ文字列」を検索するならば「(.)\1+」とするとよいでしょう。
「ぱみゅぱみゅ」のように「同じ文字列が2回並んだ文字列」ならば「(.+)\1」だとうまくいきます。

JavaScriptのmatchの戻り値

JavaScriptのmatchは正規表現に合致した文字列を配列で返します。
「g」を付けない場合と「g」を付ける場合で内容が変わります。

gを付けない場合 gを付ける場合
0個目 合致した部分全体
1個目 1個目の括弧で括られた部分
2個目 2個目の括弧で括られた部分
0個目 最初に合致した部分全体
1個目 2番目に合致した部分全体

gを付けない場合のサンプル

str="xayxbyxcy";
ret=str.match(/(x.)y/);

ret[0]="xay"
ret[1]="xa"

「x□y」という文字列を探しています。
gがないので一つ見つけたら終わりです。
戻り値の0個目は合致した部分全体です。「xay」になります。
戻り値の1個目は合致した部分のうち括弧に挟まれた部分です。「(xa)y」と見て「xa」になります。

gを付ける場合のサンプル

str="xayxbyxcy";
ret=str.match(/(x.)y/g);

ret[0]="xay"
ret[1]="xby"
ret[2]="xcy"

上のサンプルと同じく「x□y」という文字列を探しています。
gがあるので合致する文字列をすべて見付けます。
戻り値の0個目は最初に合致した文字列です。
戻り値の1個目は2番目に合致した文字列です。
戻り値の2個目は3番目に合致した文字列です。
括弧に挟まれた部分を返すようなことはありません。

長音を含む文字列を辞書順でソート

辞書の言葉の並び順はアイウエオ順ですが、「ー」という伸ばす音、長音があるときは、その前の音によって判断されます。
その前の音がア段ならば「ア」、イ段ならば「イ」となります。
例えば「ワード」ならば「ワアド」、「キー」ならば「キイ」として並び順が決まります。

ワア≫ワー≫ワアド≫ワード≫ワイ

となります。 (さらに…)

JSONの\uXXXXをデコード

TwitterAPIなどを使い、JSON形式でデータを取得した場合、文字列が次のようになっている場合があります。

\u4eca\u671d\u306f

初めて見ると「文字化けか」と思ってしまうかもしれませんが、これはJSONのルール通りなんだそうです。
この「\uXXXX」形式は「Unicode文字エスケープシーケンス」、「unicode escape sequence」などと呼ぶそうです。
2.4.1 Unicode 文字エスケープ シーケンス (C#)
Unicodeにおける文字番号を4桁の16進数に置き換えて、頭に「\u」を付けます。
これをJavaScriptを使って人間が読める形にする方法(デコード)を調べました。
単純な方法

簡単なのは次のようにJavaScriptでページに書く方法です。

document.write("\u4eca\u671d\u306f");

これで次のように表示されます。

今朝は

関数を使う方法

「json_str_decode」という関数を作ってみました。
このケースでは「\」が(JavaScriptの)エスケープシーケンスに該当してしまうので「\\」のようにしないと正しく認識しません。

document.write(json_str_decode("\\u4eca\\u671d\\u306f"));
function json_str_decode(str){
  arrs=str.match(/\\u.{4}/g);
  var t="";
  for(i=0;i<arrs.length;i++){
    t+=String.fromCharCode(arrs[i].replace("\\u","0x"));
  }
  return(t);
}

次のようにテキストエリアなどに貼り付けて使う場合には「\\」とする必要がありません。

<textarea id="ta">\u4eca\u671d\u306f</textarea>
<div id="mydiv"></div>
var a=document.getElementById("ta").value;
document.write(json_str_decode(a));

「東京電力の電気使用状況 API」を使う

東京電力から電力の使用状況が公開されましたが、これをJSON形式で扱えるAPIを公開しているサイトがありました。
東京電力の電気使用状況 API

これを試してみます。
JSON形式なのでJavaScriptで簡単に使うことができます。
データ例は次の通りです。

{"hours":[2990,2850,2770,2710,2700,2830,3100,3350],"capability":3850,"updated":"2011-03-25 08:05:00"}

hoursは午前0時から1時間毎の電力です。現時点までの情報が配列で得られます。単位は万キロワット。
capabilityは電力の最高限度です。
updatedは更新時刻です。

サンプル

サンプルは次の通りです。
なおJavaScriptの部分についてはjQueryを使っています。

HTML
<html>
<body>
<div id="main"></main>
</body>
</html>
JavaScript
var td = new Date();
var ymd = td.getFullYear() * 10000 + (td.getMonth() + 1) * 100 + td.getDate();
$.getJSON("http://denki.cuppat.net/data/" + ymd + ".json", function(json){
  $("#main").append("<p>" + td.getDate() + "日</p>");
  var hrs = json.hours;
  var cap = json.capability;
  var upd = json.updated;
  $("#main").append("<ul>");
  var temp;
  for(var i = 0 ; i < hrs.length ; i++){
    temp = i + "時 " + hrs[i] + "万kW (" + Math.floor(hrs[i] * 100 / cap) + "%)";
    $("#main ul").append("<li>" + temp + "</li>");
  }
  $("#main").append("<p>" + upd.replace(/.* (..):(..):.*/,"$1:$2 更新")+"</p>");
});

Googleマップ KML/CSV相互変換

Googleマップは、位置情報をプロットして、自分の地図(マイマップ)をつくることができます。
このデータはKMLという形式でエクスポートすることができます。
これをCSVに変換するためのツールを作りました。

Googleマップ KML/CSV相互変換

CSVに変換し、Excelなどで編集した後、またKMLに変換して、マイマップにインポートすることもできます。 (さらに…)

厄年早見表

初詣に行ったところ、すでに厄年を過ぎていたことに気付いた次第。
何が分かりにくいかというと「数え年」の意味。
生まれたときに既に1歳、年を越すと1歳プラス、というのが数え年。
Wikipediaの説明は次の通り。

元日から誕生日前日午後12時までは「満年齢+2」、それ以降は「満年齢+1」で計算する。

これは間違いではないのですが、本質が分かっていないような気がします。
数え年の特徴は「同じ年に生まれた人は同じ数え年」というところなのです。
となると生まれた日はどうでもよくて、生まれた年だけを考えればよく、
「数え年=今年-生まれた年+1」
で求まります。

これを踏まえて「厄年早見表」を作りました。

厄年早見表

「その年に厄年を迎えるのは西暦何年生まれの人か」
「その年に生まれた人の厄年は西暦何年か」
が求まります。

新しい記事 | 古い記事

タグ

カテゴリー

最近の投稿

最近のコメント

固定ページ

アーカイブ

stabucky

写真

メタ情報