JavaScriptでOR検索を実装した話(3Dマップ上に〜その3)

4990 0

前回の続き。
まさかのAND検索からOR検索へ突然の仕様変更…。

げんなりしてしまうところではありますが、実際の案件の中でも起こり得ることです。気を取り直して実装していきましょう。

AND検索が条件をすべて満たすものを抽出する方式だったことに対し、OR検索はいずれかの条件を満たすものを抽出する方式です。

AND検索のスクリプトからの変更点は3つの関数のみ(といっても_markersToggle()関数はほぼほぼ一緒)です。
大きく変更があるのは2回目以降の絞り込みに仕様する_research()関数くらいです。

AND検索での_research関数は絞り込み済みデータからさらに条件に合うものを抽出する仕組みになっていましたが、OR検索では前述の通り、全件捜査->新しい配列(結果)へpush->絞り込み済みデータとconcat(連結)(+重複したindexを間引く)という仕組みに。

完成型

	function _markersToggle(searchTrg,resultLength){
		var checkCount = 0;

		if(searchTrg === 'japan' && now_result instanceof Array){
			for (var i = 0; i < resultLength; i++) {
				_toggeleInfo(true,TMPresultData[i])
			}
		}else if(searchTrg === 'japan' && !now_result){
			for (var i = 0; i < resultLength; i++) {
				if(i === TMPresultData[checkCount]){ checkCount++;continue; }
				_toggeleInfo(false,i)
			}
		}else{
			if(COMMON.MODE === '3D'){
				if(now_result instanceof Array){
					for (var i = 0; i < resultLength; i++) {
						_globeMarkerToggle(true,TMPresultData[i])
					}
				}else{
					for (var i = 0; i < resultLength; i++) {
						if(i === TMPresultData[checkCount]){ checkCount++;continue; }
						_globeMarkerToggle(false,i)
					}
				}
			}else{
				if(now_result instanceof Array){
					for (var i = 0; i < resultLength; i++) {
						_mapMarkerToggle(true,TMPresultData[i])
					}
				}else{
					for (var i = 0; i < resultLength; i++) {
						if(i === TMPresultData[checkCount]){ checkCount++;continue; }
						_mapMarkerToggle(false,i)
					}
				}
			}
		}
	}

	function _search(data,type,refine){
		var searchTrg = (type) ? 'japan' : 'world';
		var tmp = [];
		var key = data[0];
		var val = data[1];
		if(searchTrg === 'japan'){
			var searchData = db2;
			var now_result = resultData2;
		}else{
			var searchData = db;
			var now_result = resultData;
		}

		var count = (searchTrg === 'japan') ? searchData.length : COMMON.markers;

		var TMPresultData = [];
		var loopRsult = [];
		for (var i = 0; i < count; i++) {
			var checkData = searchData[i]; //絞り込み済みデータを抽出

			if(checkData[key] instanceof Array){
				var tmpV = checkData[key];
				var childlength = tmpV.length;
				var tm_result = false;
				for (var ci = 0; ci < childlength; ci++) {
					if( tmpV[ci] === val ){ tm_result = true; }
				}
				var result = (tm_result) ? true : false;
			}else{
				var result = (checkData[key] === val) ? true : false;
			}

			if(i === 0 && searchTrg !== 'japan'){result = true}

			tmp[i] = result;
			if(tmp[i]){ loopRsult.push(i) }
		}

		if(now_result instanceof Array){
			TMPresultData = now_result.concat(loopRsult);
			TMPresultData = TMPresultData.filter(function(x,i,self){
				return self.indexOf(x) === i
			})
			var resultLength = TMPresultData.length;
		}else{
			TMPresultData = loopRsult;
			var resultLength = searchData.length;
		}

		_markersToggle(searchTrg,resultLength);

		if(searchTrg === 'japan'){
			resultData2 = TMPresultData;
			countNumber()
			saveStorage()
		}else{
			resultData = TMPresultData;
		}
	}

	function _research(data,type){ //絞り込み2回目以降
		var searchTrg = (type) ? 'japan' : 'world';
		if(searchTrg === 'japan'){
			var searchData = db2;
		}else{
			allHide(COMMON.MODE);
			var searchData = db;
		}
		var newData = [];
		var newDataLenght = data.length;

		for (var i = 0; i < newDataLenght; i++) {
			var str = data[i].split(':')
			newData.push(str)
		}

		newDataLenght = newData.length;

		var TMPresultData = [];

		for(var i = 0; i < newDataLenght; i++){
			var loopTmp = [];
			var loopResult = [];

			if(i > 0){
				if(searchTrg === 'japan' && TMPresultData.length === searchData.length){
					break;
				}else if(searchTrg === 'world' && TMPresultData.length === searchData.length){
					break;
				}
			}
			var count = (searchTrg === 'japan') ? searchData.length : COMMON.markers;
			var key = newData[i][0];
			var val = newData[i][1];

			for (var j = 0; j < count; j++) {
				var checkData = searchData[j];

				if(checkData[key] instanceof Array){
					var tmpV = checkData[key];
					var childlength = tmpV.length;
					var tm_result = false;
					for (var ci = 0; ci < childlength; ci++) {
						if( tmpV[ci] === val ){ tm_result = true; } 
					}
					var result = (tm_result) ? true : false;
				}else{
					var result = (checkData[key] === val) ? true : false;
				}

				if(j === 0 && searchTrg !== 'japan'){result = true}

				loopTmp[j] = result;
				if(loopTmp[j]){ loopResult.push(j) } // 条件に合致したdb上のindex番号を抽出
			}
			TMPresultData = TMPresultData.concat(loopResult);
			TMPresultData = TMPresultData.filter(function(x,i,self){
				return self.indexOf(x) === i
			})

		}
		loopTmp = null;
		loopResult = null;

		//上のfor分の結果からまとめて表示するマーカーを処理
		var resultLength = TMPresultData.length;
		var checkCount = 0;

		if(searchTrg === 'japan'){
			for (var i = 0; i < resultLength; i++) {
				_toggeleInfo(true,TMPresultData[i]);
			}
			resultData2 = TMPresultData;
			countNumber()
			saveStorage()
		}else{
			if(COMMON.MODE === '3D'){
				for (var i = 0; i < resultLength; i++) {
					_globeMarkerToggle(true,TMPresultData[i]);
				}
			}else{
				for (var i = 0; i < resultLength; i++) {
					_mapMarkerToggle(true,TMPresultData[i]);
				}
			}
			resultData = TMPresultData;
		}

	}

最終的な処理以外は_search()関数と処理があんまり変わらないことになっていますので、うまく条件分岐などで一つにまとめたり途中で分岐させるなりしたほうがメンテナンス性が上がるでしょう。

まとめ

なにかしら特定の機能(既出のものの改良、新しい機能とも)を作成する為には

  • どういった処理を行う必要があるか、細かく分解する
  • 分解した一つ一つ=部品をつくっていく
  • 部品を組み立てる
  • 動作を確認し、誤作動がある場合は検証していく

という工程をとれば、基本何でも作れるというものではないかな、と思います。

今回のような絞り込みはunderscore.jsのwhere()などでも可能です。しかしながら、『欲しい形状にデータを加工したい』となった時にそれらの関数を改造するにも相応の知識が必要です。車輪の再開発も時にはあえて行うことで自分の力になるものではないかな、と考えています。

JSON

Comments

Add a Comment

メールアドレスが公開されることはありません。

認証コード * Time limit is exhausted. Please reload CAPTCHA.

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください