配列と連想配列とJSONどれも似ていて扱い方をいつも忘れるので、1ページ内に出来るだけ使い方をまとめました。
オブジェクト (Object)(≒連想配列、ディクショナリ)
- 連想配列と言う人もいますがJavascriptではオブジェクトと言うのが正式名称。
- 連想配列はキーと値がセットになって、キーで値を取り出せるデータ構造の事で、JavascriptのオブジェクトやPythonのDictionaryも連想配列の一種です。 JSONは連想配列に似ていますが、キーで値を取り出せず、データの表現方法です。
- PythonのDictionaryに近い。 オブジェクトリテラルとも呼ばれます。
- 任意の文字列のキー(=プロパティとも言われる)と値のペアのデータ構造。
- オブジェクトの値が文字列の場合はダブルクオーテーションで囲っても全てシングルクオーテーションで表示される。
オブジェクトの宣言
let myObj1 = new Object(); let myOjb2 = {key0:321, Orange: 200, Apple:"red"};
値の変更
let myObj2 = {key0:321, Orange: 200, Apple:"red"}; myObj2.key0 = 123; //既存のキー名をチェーンで上書き myObj2["key0"] = 123; //既存のキー名を添字で上書き
キーの追加
//アルファベット順でなく、追加した順に右側に追加される// let myObj1 = new Object(); myObj1.name = "ichiri"; //存在しないキー名をチェーンで追加 myObj1.gender = "Male"; myObj1["place"] = "Osaka"; //存在しないキー名を添字(Index)で追加
キーを変数で追加
let myObj1 = new Object(); myObj1.gender = "Male"; const foo = 1 + 2; myObj1[foo] = "ichiri"; //変数を[ ]で括るだけ console.log(myObj1); //結果 ちゃんとキーで3が追加されています。 { gender: 'Male' , '3': 'ichiri' }
キー削除 delete 演算子
let myObj2 = {key0:321, Orange: 200, Apple:"red"}; delete myObj2.key0; delete myObj2["Apple"]; delete myObj2; // これは出来ない。 オブジェクトごと削除は不可。
キーの値取出し
let myObj2 = {key0:321, Orange: 200, Apple:"red"}; let value = myObj2.key0; let value = myObj2["key0"];
値一括取出し
let myObj2 = {key0:321, Orange: 200, Apple:"red"}; for (key in myObj2){ console.log(key + "::::" + myObj2[key]); }
キー一括取得
let myObj2 = {key0:321, Orange: 200, Apple:"red"}; console.log(Object.keys(myObj2));
一括コピー
let myObj2 = {key0:321, Orange: 200, Apple:"red"}; let myObj4= { ...myObj2 }; //spread オペレータ(ES6以降) let myObj5= Object.assign({}, myDict2 ); myObj4 = myObj2 ; //この方法はダメ! myDict2.key0=654とすると、myDict4.key0も654となる。 //値をコピーしているのでなく、参照アドレスをコピーしているだけ。
キー名でのソート
let fruits = [ { name: 'apple', value: 100 }, { name: 'orange', value: 80 }, { name: 'melon', value: 3000 }, { name: 'banana', value: 150 }, { name: 'strawberry', value: 500 }, ]; keys = Object.keys(fruits[0]); keys.sort();
値でのソート
let fruits = [ { name: 'apple', value: 100 }, { name: 'orange', value: 80 }, { name: 'melon', value: 3000 }, { name: 'banana', value: 150 }, { name: 'strawberry', value: 500 }, ]; fruits.sort(function(a,b){ return (a.value - b.value); });
連結
let myObj4 = { a: 1, b: 2, c: 3 }; let myObj5 = { d: 4, e: 5, f: 6 }; let result1 = Object.assign(myObj4, myObj5); //同じキー名があった場合は、右側のobjの値が採用される。 let result2 = {...myObj4, ...myObj5};
キー名の変更
//新しく変更したキーが一番右に来てしまいます。 順番が変わりますが、この方法が一番簡単。 //順番も変わらなく複数のキー名を一括方式はこのページの下に例を置いていますが、ややこしいです。 let myObj2 = {key0:321, Orange: 200, Apple:"red"}; myObj2.new_name = myObj2.key0; //値をまず新しいキーに退避 delete myObj2.key0;
値が存在するインデックス検索 findIndex()
//(存在しない場合は-1が返る。 ifで使用する際、-1は真となるので注意。) let fruits = [ { name: 'apple', value: 100 }, { name: 'orange', value: 80 }, { name: 'melon', value: 3000 }, { name: 'banana', value: 150 }, { name: 'strawberry', value: 500 }, ]; let index = fruits.findIndex((data) => data.name === 'melon'); //2 が返る。
条件指定して取出し filter()
let fruits = [ { name: 'apple', value: 100 }, { name: 'orange', value: 80 }, { name: 'melon', value: 3000 }, { name: 'banana', value: 150 }, { name: 'strawberry', value: 500 }, ]; let index = fruits.filter((data) => data.value >= 200); console.log(index); // [ { name: 'melon', value: 3000 }, { name: 'strawberry', value: 500 } ] console.log(index.length); //2
- オブジェクトではpush、popは使えない。
- キー名が数字のみの場合、アクセスできない。
長さ確認 Object.keys(obs)
let apple= { name: 'apple', value: 100, qty:300, location:'osaka' }; console.log(Object.keys(apple).length);
ループ forEach
let apple= { name: 'apple', value: 100, qty:300, location:'osaka' }; Object.keys(apple).forEach(function (key) { console.log(`${key}: ${apple[key]}`; });
ループ for in
- 配列はfor of。 オブジェクトはfor in。
let apple= { name: 'apple', value: 100, qty:300, location:'osaka' }; for (const property in apple) { console.log(`${property}: ${apple[property]}`); }
値の取出し 分割代入
const obj1 = {name:'ichiri',bloodType:'A', gender:'male'}; const {bloodType, gender, name}=obj1; obj1.name='Mike'; console.log(bloodType, gender, name); //-> A male ichiri
配列 (Array)
- 自動的に0からの数字(添字:インデックス)が割り当てられる。
- 配列の中にオブジェクトを入れる事ができる。
配列の宣言必要
let myArray0 = new Array(3,2); //配列長を指定して空配列を宣言。3x2の2次元配列。 let myArray0 = []; // 上と同じの簡単記述方法。 let myArray1 = [123,"ichiri",'apple', "banana"]; //宣言時に値を設定。 数字・文字混在可能。 let myArray2 = [123, 'ichiri', [234, 'orange']]; //配列内に配列混在可能。 let myArray3 = [123, 'ichiri', { name: 'banana', price: 80 }]; // 配列内にオブジェクト混在可能 let banana_price = 95; let myArray4 = [123, 'ichiri', { name: 'banana', price: banana_price}]; // 配列内に変数混在可能 let myArray5 = new Array(5); // 空配列で配列長5で宣言。 [ <5 empty items> ]
値変更
myArray1[0] = 456; myArray2[2][0] = '567'; //数字の234を文字列の'567'に変更 myArray3[2].name = 'apple'; //'banana'を'apple'に変更 myArray5[1] = 10;
配列長確認 .length
console.log(myArray1.length);
連結
let myArray1 = [1, 2, 3]; let myArray2 = [4, 5, 6]; let myArray3 = [...myArray1 , ...myArray2 ];
最後(一番右)に要素を追加 push()
let myArray3 = [123, 'ichiri', { name: 'banana', price: 80}]; myArray3.push(987); //[123, 'ichiri', { name: 'banana', price: 80}, 987]; myArray3.push(9,8,7); //[123, 'ichiri', { name: 'banana', price: 80}, 9, 8, 7]; //或いは myArray3[myArray3.length] = 987;
先頭(一番左)に要素を追加 unshift()
let myArray3 = [123, 'ichiri', { name: 'banana', price: 80}]; myArray3.unshift(987); //[987, 123, 'ichiri', { name: 'banana', price: 80}];
最後(一番右)の要素を切出す pop()
let myArray3 = [123, 'ichiri', { name: 'banana', price: 80}]; let value = myArray3.pop(); // value = { name: 'banana', price: 80 } console.log(myArray3; //[123, 'ichiri'] 最後の要素が無くなる let value = myArray3.slice(-1); // value = { name: 'banana', price: 80 } これもpopと同じ
先頭(一番左)の要素を切出す shift()
let myArray3 = [123, 'ichiri', { name: 'banana', price: 80}]; let value = myArray3.shift(); // value = 123 console.log(myArray3); //['ichiri', { name: 'banana', price: 80 }] 先頭の要素が無くなる
配列の間に追加 splice(挿入場所, 0, 挿入要素1, 挿入要素2,…)
let myArray3 = [123, 'ichiri', { name: 'banana', price: 80}]; myArray3.splice(1, 0, 'X', 'Y'); console.log(myArray3); //[ 123, 'X', 'Y', 'ichiri', { name: 'banana', price: 80 } ] //インデックス1の前に挿入される
一部を切出し slice(開始インデックス, 個数)
let value= myArray1 .splice(1, 2); //value=["ichiri",'apple'] //1から2まで切出し。endは要素数ではありません。 console.log(myArray1); //myArray1 = [123, 'banana']
一部を切出して、新しい値を挿入(=入れ替え)
slice(開始インデックス, 個数, 挿入要素1, 挿入要素2,…)
let myArray1 = [123,"ichiri",'apple', "banana"]; let value= myArray1 .splice(1, 2, 'A', 'B','C', 777); //value=["ichiri",'apple'] console.log(myArray1); //myArray1 = [123, 'A','B','B',777,'banana'] console.log(value); //value = ['ichiri','apple']
先頭に(一番左)に複数要素を追加
splice(0, 0, 挿入要素1, 挿入要素2,…)
let myArray1 = [123,"ichiri",'apple', "banana"]; value = myArray1.splice(0, 0, 'A', 'B', 'C', 777); console.log(myArray1); //['A','B', 'C', 777, 123,'ichiri','apple','banana']
最後に(一番右)に複数要素を追加
splice(myArray1.length, 0, 挿入要素1, 挿入要素2,…)
let myArray1 = [123,"ichiri",'apple', "banana"]; let value = myArray1.splice(myArray1.length, 0, 'A', 'B', 'C', 777); console.log(myArray1); //[123,'ichiri','apple','banana','A','B','C',777]
最後からn番目に要素を挿入
splice(-n, 0, 挿入要素1, 挿入要素2,…)
let myArray1 = [123, 'ichiri', 'apple', 'banana']; let value = myArray1.splice(-1, 0, 'A', 'B', 'C', 777); //後ろから一つ前に要素を挿入 console.log(myArray1); //[ 123,'ichiri','apple','A','B','C',777,'banana']
配列のコピー from()
let myArray3 = [123, 'ichiri', { name: 'banana', price: 80 }]; let myArray4 = [...myArray3]; let myArray5 = Array.from(myArray3); let myArray6 = myArray3; //この方法はダメ! myArray3[0]=234とすると、myArray4[0]も234となる。 //fromを使わない方法は、参照アドレスだけをコピーしているので実体は同じになfる。 myArray3[0] = 250; console.log(myArray3); //[ 250, 'ichiri', { name: 'banana', price: 80 } ] console.log(myArray4); //[ 123, 'ichiri', { name: 'banana', price: 80 } ] console.log(myArray5); //[ 250, 'ichiri', { name: 'banana', price: 80 } ] <---これも変わってしまう
一括計算 map(callback(value, [index], [array])[,that])
- thatはcallbackの中のthisのオブジェクト。
let myArray6 = [1,2,3]; let resultArray = myArray6.map(function( value,index,array) { return value * 2; //console.log(value,index,array); }); console.log( resultArray ); //[ 2, 4, 6 ] 配列で返ってくる。 //mapもループを回すが、valueはそのループの時に配列から取り出した値。 //indexはそのループの時に配列から取り出した値のインデックス。 //arrayそのループ時の配列。
deleteを使うと…(注意!)
let myArray1 = [123, 'ichiri', 'apple', 'banana']; delete myArray1[0]; console.log(myArray1); //[ <1 empty item>, 'ichiri', 'apple', 'banana' ] console.log(myArray1[0]); //undefined
長さ 配列名.length
- Pythonの様に多次元のshapeは使用できない。 .lengthで1次元の長さしか見れない。
[1,2,3].length;
ループ 配列名.forEach(callback(element,[index],[array])[,that])
- indexは0から始まりループが回るたびに1づつインクリメントする。
- arrayは対象の配列が毎ループどのよう変化しているか確認できる。
- forEachはbreak使用不可。
- 要素が無い場合は処理されない。[‘A’,’B,,,’C’,’D’] の時、要素2,3,4のループは実行されない。
- thatはcallbackの中のthisのオブジェクト。
let data=['A','B',,,'C','D']; data.forEach(function(value, index, array){ data[index]=value + index; console.log(value, index, array); });
ループ for of 配列名
- indexを返さない。 indexを使う場合は、.entriesを使う。
let data=['A','B',,,'C','D']; for (let i = 0; i < data.length; i++) { console.log(`${i}: ${data[i]}`); } for (value] of data()){ console.log(`Index無し:${value}`); } for (const[index, value] of data.entries()){ console.log(`${index}: ${value}`); }
reduce(callback(previousValue, currentValue[,currentIndex, array] )[,initialValue])
- Arrayで順番に値を取り出して関数を実行してくれる。
- Arrayの要素がcurrentValueに順番に入る。
- ループば始まる前は最初は初期値がpreviousValueに入る。
- returnの値がpreviousValueに入る。
- thatはcallbackの中のthisのオブジェクト。 initialValueとして初期値を与える事もある。
const array1 = [1, 2, 3, 4]; const init_Value = 100; const sum_reduce = array1.reduce( (previousValue, currentValue) => { console.log(previousValue,currentValue); return previousValue + currentValue; }, init_Value); console.log('kekka?=', sum_reduce );
値の取出し 分割代入
- 配列の中身を一括で変数に入れる事が出来る。
- spread operatorを使うと残り配列として取り込める。
- rest parameterは最後の要素にだけ設定できる。
let a = [ 1 ,2 ]; let [ b , c , d = 3] = a; // 初期値を設定できる console.log( b , c , d); //-> 1 2 3 let aa = [ 1 ,2, 5, 6, 7 ]; let [ b , c , d = 3] = aa; // aaの要素数が多くても構わない。 console.log( b , c , d); //-> 1 2 5 初期値上書き let [ b , c , ...d] = aa; // aaの要素数が多くても構わない。 spread operatorの場合、初期値を設定できない。 console.log( b , c , d); //-> 1 2 [ 5, 6, 7 ] let [ b , c , d = 3] = [10,...aa]; //受け渡し元にrest parameter設定 console.log( b , c , d); //-> 10 1 2
JSON(JavaScript Object Notation)
- オブジェクト(≒連想配列)とそっくりだが、オブジェクトでなく文字列で構造化(体系化)したもの。 JSONもは文字列だがJavascriptのオブジェクトの様に扱える。
- Javascriptのプログラム内の宣言では全体をシングルクオーテーションで括り、全てのキーと文字列値をダブルクオーテーションで括る必要がある。 キーや値にシングルクオーテーションを使うとparse時にUnexpected token ‘ エラーになります。 値の数値とnull, true, falseはダブルクオーテーションは不要。
- オブジェクト(≒連想配列)はconstructor等の関数(メソッド)も中に入っているので他言語との互換性もなく通信には適さないのですが、連想配列と同じ構造で文字だけのJSONは他言語との互換性もありクライアント(ブラウザ)とWebサーバー間の通信にも適しています。
- JSONはオブジェクトでないので、追加や削除やキーによる取出しは出来ません。 オブジェクトに変換して操作して、操作が終わればJSONに変換しなければなりません。
宣言
let myJSON1="{ \"name\": \"ken\", \"age\": 26 }"; //これはOK。しかし上記に変換されます。 let notJSON="{ 'name': 'ken', 'age': 26 }"; //これはJSON.parseでエラーになります。 let myObj = { name: 'Chris', age: 38 }; //これはオブジェト
連想配列をJSONに変換 JSON.stringify() — 文字列化
let myObj = { name: 'Chris', age: 38 }; let myJSON=JSON.stringify(myObj); console.log(myObj); //{ name: 'Chris', age: 38 } console.log(myJSON); //{"name":"Chris","age":38}
JSONを連想配列に変換 JSON.parse()
let myJSON0='{ "name": "ken", "age": 26 }'; let myObj1 = JSON.parse(myJSON0);
JSONかどうかの確認は、JSON.parseでエラーにならなければJSONです。
var myObj2 = ['{"name": "tarou", "age": 38, "location": "大阪"}', '{"name": "tarou", "age": 38, "location": "大阪"}', '{"name": "tarou", "age": 38, "location": "大阪"}']
- 数値で小数点の前に必ず数字が必要。 0.32はオッケー。 .32はエラー。
- 数字でNAN, Infinityはエラー。
- 配列やオブジェクト(連想配列)で最後の後にカンマを置くのは禁止。
- 値の取出しやdelete, pop, pushはJSONのままではできない。 JSON.parse()でオブジェクトに変換して操作し、JSON.stringify()で再度JSONに戻す。
- JSON内にキーとなるところが数字のみの文字列の場合、JSON.parse()でエラーで検出できないが、文字列となりオブジェクトに変換できない。
let myJSON = '{ "123": 40, "name": "tara" }'; let myObj1 = JSON.stringify(myJSON); console.log(myJSON); //{ "123": 40, "name": "tara" } console.log(myObj1); //"{ \"123\": 40, \"name\": \"tara\" }"
JSONかどうかの確認
組込み機能ではないので、よくある下のコードで代用する。
function is_json(data) { try { JSON.parse(data); } catch (error) { return false; } return true; }
他プログラム言語のJSONとオブジェクトへの変換命令
プログラム言語 | JSONへの変換 | オブジェクトへの変換 |
---|---|---|
Javascript | JSON.stringfiy() | JSON.parse() |
PHP | json_encode() | json_decode() |
Python | Json.dump() | Json.load() |
C# | DataContractJsonSerializer、DynamicJson |
おまけ
配列内オブジェクトから正規表現で一括取り出し
Formのinput情報をserializeArrayで取り出すとnameとvalueのオブジェクトが配列になったこの形式ででてくる。 RegExpを使い前方一致で取出し。 filterは複数取り出せたが、findでは最後にマッチしたものしか取り出せない。
let a= [{name : 'ichiri-age-7', value: "50"}, {name : 'ichiri-id-7', value: "80"}, {name : 'ichiri-name-8', value: "ok"}, {name : 'ichiri-age-8', value: "60"}, {name : 'ichiri-id-8', value: "100"}, ]; let regex = RegExp('^ichiri-id'); let arr = a.filter(value => regex.test(value.name)); //let arr = a.filter(function (value) {return regex.test(value.name); }); console.log(arr);
オブジェクトの複数キー名の変更
キーの順番が変わらず一括変更できる
let personA = { name : "ichiri", city: "Japan", type : "A" }; // 変更するプロパティ名のオブジェクトを作成 let newKeys = { name: "familyName", city: "birthPlace" }; // メソッド呼び出し personA = renameKeys(personA, newKeys); function renameKeys(obj, newKeys) { // 再マッピング const keyValues = Object.keys(obj).map(key => { const newKey = newKeys[key] || key; return { [newKey]: obj[key] }; }); return Object.assign({}, …keyValues); } console.log(personA); // {familyName: "ichiri", birthPlace: "Japan", type: "A"}
コメント