yumetodoの旅とプログラミングとかの記録

旅や登山の記録やプログラミング関連の話とかフリーソフト紹介とか

Google Apps Scriptで配列を返す関数を作る:居住市区町村の文字列正規化

みらい研究室実行委員会の6月のイベントのアンケート解析で、住んでいる区市町村名を問う項目の集計を備え付けのifやらleftやらmid関数でやりくりするのは限界があったので、
Google Apps Script(通称GAS、ExcelVBAみたいな位置で言語的にはJavaScript)で関数を作りました。

ただ、データ数が2000件近くあるので全セルにこの作った関数を呼ぶ式を打つと

エラー: Script invoked too many times per second for this Google user accout.

といった具合に怒られるので対策が必要でした。

Google スプレッドシートでカスタム関数を多くのセルで呼び出しエラーが表示される場合、配列を返す関数(配列数式)に変更する。または、新しいスプレッドシートを利用。 | すぐに忘れる脳みそのためのメモ
を参考に配列を返す関数を作ります。

最も注意するべきなのは、自作関数の引数にある適当な範囲を渡した時の引数は、「stringのArrayのArray」ということです。断じて「stringのarray」ではありません。

function remove_prefectures_name(str){
	if(typeof str !== "string") return "error: unexpected input.";
	var buf = "";
	var tmp = str.charCodeAt(2);
	if("道".charCodeAt(0) === tmp || "都".charCodeAt(0) === tmp || "府".charCodeAt(0) === tmp || "県".charCodeAt(0) === tmp){
		buf = str.slice(3);
	}
	else if("県".charCodeAt(0) === str.charCodeAt(3)){
		buf = str.slice(4);
	}
	return (buf.length === 0) ? str : buf;
}
function match_in_array(arr, str){
	var is_matched = false;
	for(var i = 0; !is_matched && i < arr.length; ++i){
		is_matched = (arr[i] === str);
	}
	return is_matched;
}
function add_City(str){
	var case_do_not_add_City = ["市", "区", "町", "村", "県", "都", "道", "府", "県"];
	return (match_in_array(case_do_not_add_City, str.slice(-1))) ? str : str + "市";
}
function normalize_adress_helper(main_input, case1_input, case4_input){
	if(typeof main_input !== "string" || typeof case1_input !== "string" || typeof case4_input !== "string"){
		throw new TypeError("main_input(type:" + typeof main_input + ")unexpected input.");
	}
	var re = "";
	switch(main_input){
	case "1.東京23区内":
		re = (case1_input === "無記入" || case1_input === "") ? "無記入" : "1-" + case1_input + "区";
	break;
	case "4.その他":
		var do_not_edit = ["アメリカ", "韓国", "korea"];
		re = (case4_input === "無記入" || case4_input === "") ? "無記入" :  (match_in_array(do_not_edit, case4_input)) ? case4_input : add_City(remove_prefectures_name(case4_input));
	break;
	default:
		re = main_input;
	}
	return re;
}
function normalize_adress(main_input, case1_input, case4_input){
	if(typeof main_input === "string" && typeof case1_input === "string" && typeof case4_input === "string"){
		return normalize_adress_helper(main_input, case1_input, case4_input);
	}
	else if(Array.isArray(main_input) && Array.isArray(case1_input) && Array.isArray(case4_input) && main_input.length == case1_input.length && case1_input.length == case4_input.length){
		var re = [];
		for(var i = 0; i < main_input.length; ++i){
			re.push(normalize_adress_helper(main_input[i][0], case1_input[i][0], case4_input[i][0]));
		}
		return re;
	}
	else{
		throw new TypeError("main_input(type:" + typeof main_input + ")unexpected input.");
	}
}