別の外部ライブラリを含めることを気にせず、LINQに慣れている場合は、これにlinq.jsを使用できます。
var stuff = {
'Steam' : { needs: ['Water', 'Fire'] },
'Mud' : { needs: ['Water', 'Earth'] },
'Rock' : { needs: ['Mud', 'Fire'] }
// etc...
};
function Alchemy(stuff) {
var recipes =
Enumerable.From(stuff).ToLookup(
"$.Value.needs",
"$.Key",
"Enumerable.From($).OrderBy().ToString('+')"
);
this.attempt = function(elem1, elem2) {
return recipes.Get([elem1, elem2]).ToString();
};
};
var alchemy = new Alchemy(stuff);
console.log(alchemy.attempt('Fire', 'Mud')); // "Rock"
console.log(alchemy.attempt('Fire', 'Earth')); // ""
console.log(alchemy.attempt('Fire', 'Water')); // "Steam"
ノート
Enumerable.From(stuff)
stuff
オブジェクトをそのパーツKey
とパーツに分割しますValue
。
たとえば、とKey
を参照します。"Rock"
Value
{ needs: ['Mud', 'Fire'] }
ToLookup()
そこからルックアップ辞書を作成します。それは3つのパラメータを取ります:
- 何を探すか(この場合、の要素
"$.Value.needs"
)
- 一致が見つかった場合に何を返すか(この場合、結果の要素の名前、つまり
Key
)
- 辞書キーを作成する変換関数(この場合、材料の配列はソートされた文字列に変換されます:
['Mud', Fire']
になります"Fire+Mud"
)。
Get()
関数は、同じ変換関数を使用して、引数に一致するものを見つけます。
のような文字列引数"$.Value.needs"
は。の省略形であることに注意してください
function ($) { return $.Value.needs; }
。
linq.jsは、複雑なタスクをワンライナーに変換できる、より多くの便利な関数も提供します。
編集:ルックアップからすべての追加情報を返すのは、次のように簡単です。
function Alchemy(stuff) {
var recipes =
Enumerable.From(stuff).ToLookup(
"$.Value.needs",
null, // return the object unchanged
"Enumerable.From($).OrderBy().ToString('+')"
);
this.attempt = function(elem1, elem2) {
return recipes.Get([elem1, elem2]).FirstOrDefault();
};
};
console.log(alchemy.attempt('Fire', 'Mud'));
/* result
{
Key: "Rock",
Value: {
needs: ["Mud", "Fire"],
whatever: "else you had defined in {stuff}"
}
}
*/
Lookupオブジェクトの目的は、速度を上げることです。毎回オブジェクトグラフ全体をトラバースすることもできます。
function alchemy(elem1, elem2) {
return
Enumerable
.From(stuff)
.Where(function ($) {
var recipe = Enumerable.From($.Value.needs);
return recipe.Intersect([elem1, elem2]).Count() == 2;
})
.Select("{element: $.Key, properties: $.Value}")
.FirstOrDefault();
);
console.log(alchemy('Fire', 'Water'));
// {element: "Steam", properties: {needs: ["Water", "Fire"]}}
.Select()
これはオプションであることに注意してください。削除することもできます。その場合、結果は前の例と同じになります。