JavaScriptの配列 vol.3 -連想配列 ( ハッシュ ) -

JavaScriptの配列 vol.1 -配列の宣言-, JavaScriptの配列 vol.2 -配列の宣言(続)- では、Javascript における配列の宣言についてでした。

さて、今回は連想配列(ハッシュ)についての備忘録です。連想配列(ハッシュ)についてもやはりJavaScript は摩訶不思議な言語です。


1. 連想配列(ハッシュ)の宣言

(ふつうの)配列の定義同様、連想配列の定義もさまざまなバリエーションがあります。結論から言うのはおもしろくないものですが、バリエーションはあれど (1) を用いるのが連想配列であるとわかりやすくてよいと思います。


(1) オーソドックスな連想配列

var hash_sample_1 = new Array();
hash_sample_1['name']  = "真夜中ナビ 深夜営業のお店探し";
hash_sample_1['url']   = "http://www.mayonaka-navi.info/";


JavaScriptでは new していることから明らかなように、配列もオブジェクトです。以下の(2)〜(4)はこのことを利用した連想配列(ハッシュ)です。 (3),(4)は正確には配列オブジェクトではなく、単なる代用オブジェクトにすぎません。


(2) 配列オブジェクトのプロパティを用いた連想配列

var hash_sample_2 = new Array();
hash_sample_2.name = "真夜中ナビ 深夜営業のお店探し";
hash_sample_2.url  = "http://www.mayonaka-navi.info/";


(3) オブジェクトによる連想配列の代用1

var hash_sample_3 = new Object();
hash_sample_3.name = "真夜中ナビ 深夜営業のお店探し";
hash_sample_3.url  = "http://www.mayonaka-navi.info/";
/**
 * 逆にオブジェクトのプロパティを連想配列のように記述することもできる。
 * var hash_sample_3 = new Object();
 * hash_sample_3['name'] = "真夜中ナビ 深夜営業のお店探し";
 * hash_sample_3['url']  = "http://www.mayonaka-navi.info/";
 */


(4)JSONオブジェクトによる連想配列の代用2

// var obj = { プロパティ : 値, プロパティ : 値, プロパティ : 値 };//newを使わないオブジェクトの生成(JSONオブジェクトと呼ばれるそうです。)
var hash_sample_4 = { name : "真夜中ナビ 深夜営業のお店探し", url : "http://www.mayonaka-navi.info/" };
/**
 * プロパティを ' または " で括って記述してもよい
 * var hash_sample_4 = { 'name' : "真夜中ナビ 深夜営業のお店探し", 'url' : "http://www.mayonaka-navi.info/" };
 */


以上をまとめて出力してみることにします。注目は lengthプロパティ です。連想配列では lengthプロパティ は無力です。

//(1),(2)は同じ結果。(3),(4)はlengthプロパティがないので undefined となる。いずれにせよ length プロパティにより連想配列要素数を得ることはできない。
document.write("<p>");
document.write("<strong>legnthプロパティ, キー, 値 のテスト</strong><br>");
document.write("(1) 配列数:" + hash_sample_1.length + " サイト名:" + hash_sample_1['name'] + " URL:" + hash_sample_1['url'] + "<br>");
document.write("(2) 配列数:" + hash_sample_2.length + " サイト名:" + hash_sample_2['name'] + " URL:" + hash_sample_2['url'] + "<br>");
document.write("(3) 配列数:" + hash_sample_3.length + " サイト名:" + hash_sample_3['name'] + " URL:" + hash_sample_3['url'] + "<br>");
document.write("(4) 配列数:" + hash_sample_4.length + " サイト名:" + hash_sample_4['name'] + " URL:" + hash_sample_4['url'] + "<br>");
document.write("</p>");

// for in 文の結果は同じ結果になります。
document.write("<p>");
document.write("<strong>「for 〜 in 〜」文のテスト</strong><br>");
document.write("(1) " + TestForin(hash_sample_1) + " <br>");
document.write("(2) " + TestForin(hash_sample_2) + " <br>");
document.write("(3) " + TestForin(hash_sample_3) + " <br>");
document.write("(4) " + TestForin(hash_sample_4) + " <br>");
document.write("</p>");

//「for 〜 in 〜」テスト関数(2007-01-21 に訂正)
function TestForin(array){
	var msg = "";
	for(key in array){
		msg += "キー:" + key + " 値:" + array[key] + ",  ";
	}
	return msg;
}

出力結果

legnthプロパティ, キー, 値 のテスト
(1) 配列数:0 サイト名:真夜中ナビ 深夜営業のお店探し URL:http://www.mayonaka-navi.info/
(2) 配列数:0 サイト名:真夜中ナビ 深夜営業のお店探し URL:http://www.mayonaka-navi.info/
(3) 配列数:undefined サイト名:真夜中ナビ 深夜営業のお店探し URL:http://www.mayonaka-navi.info/
(4) 配列数:undefined サイト名:真夜中ナビ 深夜営業のお店探し URL:http://www.mayonaka-navi.info/

「for 〜 in 〜」文のテスト
(1) キー:name 値:真夜中ナビ 深夜営業のお店探し,  キー:url 値:http://www.mayonaka-navi.info/,   
(2) キー:name 値:真夜中ナビ 深夜営業のお店探し,  キー:url 値:http://www.mayonaka-navi.info/,   
(3) キー:name 値:真夜中ナビ 深夜営業のお店探し,  キー:url 値:http://www.mayonaka-navi.info/,   
(4) キー:name 値:真夜中ナビ 深夜営業のお店探し,  キー:url 値:http://www.mayonaka-navi.info/,  

2. 混合配列

ふつうの配列と連想配列が混合した配列についてです(混合配列とは正式な用語ではありません)。こんな配列を実際に使うことはまずないと思いますが、徹底的に勉強ということで試してみました。

var hash_sample_5 = new Array();
hash_sample_5[0] = "ふつうの配列 0個目";
hash_sample_5[1] = "ふつうの配列 1個目";
hash_sample_5[2] = "ふつうの配列 2個目";
hash_sample_5['hash_0'] = "連想配列 0個目";
hash_sample_5['hash_1'] = "連想配列 1個目";

//要素数はふつうの配列の数だけカウントするようです。
document.write("<p>");
document.write("<strong>混合配列</strong><br>");
document.write(ShowArrayInfo(hash_sample_5));
document.write("</p>");

//配列の要素数,キーと値を表示する関数
function ShowArrayInfo(array){
	var msg = "lengthプロパティ:" + array.length + "<br>";
	for(key in array){
		msg += "キー:" + key + " 値:" + array[key] + "<br>";
	}
	return msg;
}

出力結果

混合配列
lengthプロパティ:3
キー:0 値:ふつうの配列 0個目
キー:1 値:ふつうの配列 1個目
キー:2 値:ふつうの配列 2個目
キー:hash_0 値:連想配列 0個目
キー:hash_1 値:連想配列 1個目

3. 連想配列・混合配列の要素数
上記のように連想配列では lengthプロパティ が全くあてになりません。それでも場合によっては正確な配列数を把握したいときがあるかもしれません。
そういうときには凄く不器用な関数ですが以下の関数を用いればよいと思います。(もしかしたら私が無知なだけで正確にカウントできる関数 or メソッドが用意されているかも知れません。)
※ プロパティに関数やメソッドを格納(←javascriptでは可能)した配列や多次元配列ではうまくカウントしないと思います。

function CountArrayElements(array){
	var cnt = 0;
	for(key in array){ cnt++; }
	return cnt;
}
//連想配列も混合配列も正確な要素数を取得している
//hash_sample_n は上記で用いた連想配列です。
document.write("<p>");
document.write("<strong>要素数を正確にカウント</strong><br>");
document.write("(1) " + CountArrayElements(hash_sample_1) + " <br>");
document.write("(2) " + CountArrayElements(hash_sample_2) + " <br>");
document.write("(3) " + CountArrayElements(hash_sample_3) + " <br>");
document.write("(4) " + CountArrayElements(hash_sample_4) + " <br>");
document.write("(5) " + CountArrayElements(hash_sample_5) + " <br>"); //混合配列
document.write("</p>");

出力結果

要素数を正確にカウント
(1) 2 
(2) 2 
(3) 2 
(4) 2 
(5) 5


以上、javascript連想配列についてでした。

以下は上記のコピー&ペースト用のサンプルソースです。


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=shift-jis">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/css">
<title>JavaScriptの配列</title>
</head>
<body>
<script type="text/javascript">
<!--
//1. 連想配列(ハッシュ)

//配列の定義同様、連想配列の定義もさまざまなバリエーションがあります。
//バリエーションはあるものの、(1) を用いるのが連想配列だとわかりやすくてよいと思います。

//(1) 連想配列
var hash_sample_1 = new Array();
hash_sample_1['name']  = "真夜中ナビ 深夜営業のお店探し";
hash_sample_1['url']   = "http://www.mayonaka-navi.info/";

/**
 * JavaScriptでは new していることから明らかなように、配列もオブジェクトなので以下のような記述でも連想配列(ハッシュ)の代用となる。
 */

//(2) 配列オブジェクトのプロパティ
var hash_sample_2 = new Array();
hash_sample_2.name = "真夜中ナビ 深夜営業のお店探し";
hash_sample_2.url  = "http://www.mayonaka-navi.info/";

//(3) オブジェクトによる連想配列の代用1
var hash_sample_3 = new Object();
hash_sample_3.name = "真夜中ナビ 深夜営業のお店探し";
hash_sample_3.url  = "http://www.mayonaka-navi.info/";
/**
 * 逆にオブジェクトのプロパティを連想配列のように記述することもできる。
 * var hash_sample_3 = new Object();
 * hash_sample_3['name'] = "真夜中ナビ 深夜営業のお店探し";
 * hash_sample_3['url']  = "http://www.mayonaka-navi.info/";
 */

// JSONオブジェクトによる連想配列の代用2
// var obj = { プロパティ : 値, プロパティ : 値, プロパティ : 値 };//newを使わないオブジェクトの生成(JSONオブジェクトと呼ばれるそうです。)
var hash_sample_4 = { name : "真夜中ナビ 深夜営業のお店探し", url : "http://www.mayonaka-navi.info/" };
/**
 * プロパティを ' または " で括って記述してもよい
 * var hash_sample_4 = { 'name' : "真夜中ナビ 深夜営業のお店探し", 'url' : "http://www.mayonaka-navi.info/" };
 */

//(1),(2)は同じ結果。(3),(4)はlengthプロパティがないので undefined となる。いずれにせよ length プロパティにより連想配列要素数を得ることはできない。
document.write("<p>");
document.write("<strong>legnthプロパティ, キー, 値 のテスト</strong><br>");
document.write("(1) 配列数:" + hash_sample_1.length + " サイト名:" + hash_sample_1['name'] + " URL:" + hash_sample_1['url'] + "<br>");
document.write("(2) 配列数:" + hash_sample_2.length + " サイト名:" + hash_sample_2['name'] + " URL:" + hash_sample_2['url'] + "<br>");
document.write("(3) 配列数:" + hash_sample_3.length + " サイト名:" + hash_sample_3['name'] + " URL:" + hash_sample_3['url'] + "<br>");
document.write("(4) 配列数:" + hash_sample_4.length + " サイト名:" + hash_sample_4['name'] + " URL:" + hash_sample_4['url'] + "<br>");
document.write("</p>");

// for in 文の結果は同じ結果。
document.write("<p>");
document.write("<strong>「for 〜 in 〜」文のテスト</strong><br>");
document.write("(1) " + TestForin(hash_sample_1) + " <br>");
document.write("(2) " + TestForin(hash_sample_2) + " <br>");
document.write("(3) " + TestForin(hash_sample_3) + " <br>");
document.write("(4) " + TestForin(hash_sample_4) + " <br>");
document.write("</p>");

//「for 〜 in 〜」テスト関数(2007-01-21 に訂正)
function TestForin(array){
	var msg = "";
	for(key in array){
		msg += "キー:" + key + " 値:" + array[key] + ",  ";
	}
	return msg;
}


//2. 混合配列
//ふつうの配列と連想配列が混合した配列(混合配列とは正式な用語ではありません。)
var hash_sample_5 = new Array();
hash_sample_5[0] = "ふつうの配列 0個目";
hash_sample_5[1] = "ふつうの配列 1個目";
hash_sample_5[2] = "ふつうの配列 2個目";
hash_sample_5['hash_0'] = "連想配列 0個目";
hash_sample_5['hash_1'] = "連想配列 1個目";

//要素数はふつうの配列の数だけ
document.write("<p>");
document.write("<strong>混合配列</strong><br>");
document.write(ShowArrayInfo(hash_sample_5));
document.write("</p>");

//配列の要素数,キーと値を表示する関数
function ShowArrayInfo(array){
	var msg = "lengthプロパティ:" + array.length + "<br>";
	for(key in array){
		msg += "キー:" + key + " 値:" + array[key] + "<br>";
	}
	return msg;
}




//3. 連想配列・混合配列の要素数
//上記のように連想配列では lengthプロパティ が全くあてになりません。それでも場合によっては正確な配列数を把握したいときがあるかもしれません。
//そういうときには凄く不器用な関数ですが以下の関数を用いればよいと思います。(もしかしたら私が無知なだけで、正確にカウントできる関数 or メソッドがあるかも知れません。)
//くどいようですが、混合配列という用語はありません。便宜上そう呼んでいるだけです。
function CountArrayElements(array){
	var cnt = 0;
	for(key in array){ cnt++; }
	return cnt;
}
//連想配列も混合配列も正確な要素数を取得している
document.write("<p>");
document.write("<strong>要素数を正確にカウント</strong><br>");
document.write("(1) " + CountArrayElements(hash_sample_1) + " <br>");
document.write("(2) " + CountArrayElements(hash_sample_2) + " <br>");
document.write("(3) " + CountArrayElements(hash_sample_3) + " <br>");
document.write("(4) " + CountArrayElements(hash_sample_4) + " <br>");
document.write("(5) " + CountArrayElements(hash_sample_5) + " <br>");
document.write("</p>");

// -->
</script>
<body>
<html>