ITコンサルの日常

ITコンサル会社に勤務する普通のITエンジニアの日常です。

二次元配列を複数ソートキーを指定してソート

SQLでいうところの、
ORDER BY A ASC, B DESC
みたいな、複数の項目をソートキーに指定するような処理です。
使い方はこんな感じ。

var arr = [
	[2, 2, 2], 
	[2, 2, 1], 
	[2, 1, 2], 
	[2, 1, 1], 
	[1, 2, 2], 
	[1, 2, 1], 
	[1, 1, 2], 
	[1, 1, 1]	
];

// 3番目の項目を昇順(asc)に、2番目の項目を降順(desc)にソート。
var sortFunction = makeSortFunction([2, "a", 1, "d"]);
var sortedArr = arr.sort(sortFunction);

makeSortFunctionでソート用の比較関数を定義して返してます。関数から関数を返すって辺りがちょっとJavaScriptっぽい。
で、makeSortFunctionの中身はこんなん。

function makeSortFunction(sortCondition)
{
	var i;
	var result = "";
	var resultHantei =	"if(result != 0) " + 
						"{ " + 
						" return result; " + 
						"} ";

	result += "var result; ";

	if(sortCondition.length % 2 == 1)
	{
		sortCondition.push("a");
	}

	for(i = 0; i<sortCondition.length; i+=2)
	{
		var col = sortCondition[i];
		var order = sortCondition[i + 1];
		var ret = (order == "a") ? 1 : -1;

		result += "result = (a[" + col + "] == b[" + col + "]) ? 0 : (a[" + col + "] > b[" + col + "]) ? " + ret + " : " + (ret * (-1)) + "; ";
		result += resultHantei;
	}

	result += "return result;";

	return new Function("a", "b", result);
}

むちゃくちゃ苦しいです(T_T)
最初の使い方の例でいくと、こんな関数を組み立てて返します。

function sortF(a, b)
{
	var result;

	result = (a[2] == b[2]) ? 0 : (a[2] > b[2]) ? 1 : -1;
	if(result != 0)
	{
		return result;
	}

	result = (a[1] == b[1]) ? 0 : (a[1] > b[1]) ? -1 : 1;
	if(result != 0)
	{
		return result;
	}

	return result;
}

つまり、第一キーが違う場合結果が非ゼロになるので即リターンし、第一キーが同じ場合は次のキーの比較を行うということを延々と繰り返します。
なんだか去年も似たようなことやって、もっと便利なものがあるとか教えてもらったような気がするのですが、これももっとちゃんとしたのあるんでしょうねえ。
まあそもそも、SQLでやればいいじゃんってのもありますが(汗
ちょっとJavaScriptっぽいの書いてみたかったということで。