オブジェクトの配列があり、特定のオブジェクトプロパティでそれらのオブジェクトを比較したい。これが私の配列です:
var myArray = [
{"ID": 1, "Cost": 200},
{"ID": 2, "Cost": 1000},
{"ID": 3, "Cost": 50},
{"ID": 4, "Cost": 500}
]
具体的には「コスト」をゼロにし、最小値と最大値を取得したいと思います。コスト値を取得し、それらをjavascript配列にプッシュしてから、 Fast JavaScript Max/Min を実行できることを理解しています。
ただし、中央の配列ステップをバイパスし、オブジェクトのプロパティ(この場合は「コスト」)を直接オフにすることにより、これを行う簡単な方法はありますか?
この場合の最速の方法は、すべての要素をループして、これまでの最高値/最低値と比較することです。
(この単純な操作では、配列の作成、配列メソッドの呼び出しはやりすぎです)
// There's no real number bigger than plus Infinity
var lowest = Number.POSITIVE_INFINITY;
var highest = Number.NEGATIVE_INFINITY;
var tmp;
for (var i=myArray.length-1; i>=0; i--) {
tmp = myArray[i].Cost;
if (tmp < lowest) lowest = tmp;
if (tmp > highest) highest = tmp;
}
console.log(highest, lowest);
Reduceは次のようなものに適しています:オブジェクトの配列に対して集約操作(min、max、avgなど)を実行し、単一の結果を返す:
myArray.reduce(function(prev, curr) {
return prev.Cost < curr.Cost ? prev : curr;
});
...またはその内部関数をES6関数構文で定義できます:
(prev, curr) => prev.Cost < curr.Cost ? prev : curr
キュートになりたい場合は、これを配列にアタッチできます。
Array.prototype.hasMin = function(attrib) {
return this.reduce(function(prev, curr){
return prev[attrib] < curr[attrib] ? prev : curr;
});
}
今、あなたは言うことができます:
myArray.hasMin('ID') // result: {"ID": 1, "Cost": 200}
myArray.hasMin('Cost') // result: {"ID": 3, "Cost": 50}
配列の変更を気にしない場合は、 sort
を使用します。
myArray.sort(function (a, b) {
return a.Cost - b.Cost
})
var min = myArray[0],
max = myArray[myArray.length - 1]
Rob Wの答え は本当に正しいもの(+1)ですが、ただの楽しみのために:あなたが「賢い」になりたいなら、あなたはできますこのようなことをしてください:
var myArray =
[
{"ID": 1, "Cost": 200},
{"ID": 2, "Cost": 1000},
{"ID": 3, "Cost": 50},
{"ID": 4, "Cost": 500}
]
function Finder(cmp, arr, attr) {
var val = arr[0][attr];
for(var i=1;i<arr.length;i++) {
val = cmp(val, arr[i][attr])
}
return val;
}
alert(Finder(Math.max, myArray, "Cost"));
alert(Finder(Math.min, myArray, "Cost"));
または、深くネストされた構造がある場合は、もう少し機能的になり、以下を実行できます。
var myArray =
[
{"ID": 1, "Cost": { "Wholesale":200, Retail: 250 }},
{"ID": 2, "Cost": { "Wholesale":1000, Retail: 1010 }},
{"ID": 3, "Cost": { "Wholesale":50, Retail: 300 }},
{"ID": 4, "Cost": { "Wholesale":500, Retail: 1050 }}
]
function Finder(cmp, arr, getter) {
var val = getter(arr[0]);
for(var i=1;i<arr.length;i++) {
val = cmp(val, getter(arr[i]))
}
return val;
}
alert(Finder(Math.max, myArray, function(x) { return x.Cost.Wholesale; }));
alert(Finder(Math.min, myArray, function(x) { return x.Cost.Retail; }));
これらは、より便利な/特定の形式に簡単にカリー化できます。
Math
関数を使用し、map
で必要な値を取り出します。
Jsbinは次のとおりです。
https://jsbin.com/necosu/1/edit?js,console
var myArray = [{
"ID": 1,
"Cost": 200
}, {
"ID": 2,
"Cost": 1000
}, {
"ID": 3,
"Cost": 50
}, {
"ID": 4,
"Cost": 500
}],
min = Math.min.apply(null, myArray.map(function(item) {
return item.Cost;
})),
max = Math.max.apply(null, myArray.map(function(item) {
return item.Cost;
}));
console.log('min', min);//50
console.log('max', max);//1000
更新:
ES6を使用する場合:
var min = Math.min.apply(null, myArray.map(item => item.Cost)),
max = Math.max.apply(null, myArray.map(item => item.Cost));
Array.prototype.reduce() を使用すると、コンパレータ関数をプラグインして、配列内の最小、最大などの項目を決定できます。
var items = [
{ name : 'Apple', count : 3 },
{ name : 'Banana', count : 10 },
{ name : 'Orange', count : 2 },
{ name : 'Mango', count : 8 }
];
function findBy(arr, key, comparatorFn) {
return arr.reduce(function(prev, curr, index, arr) {
return comparatorFn.call(arr, prev[key], curr[key]) ? prev : curr;
});
}
function minComp(prev, curr) {
return prev < curr;
}
function maxComp(prev, curr) {
return prev > curr;
}
document.body.innerHTML = 'Min: ' + findBy(items, 'count', minComp).name + '<br />';
document.body.innerHTML += 'Max: ' + findBy(items, 'count', maxComp).name;
これはより良い解決策です
var myArray = [
{"ID": 1, "Cost": 200},
{"ID": 2, "Cost": 1000},
{"ID": 3, "Cost": 50},
{"ID": 4, "Cost": 500}
]
var lowestNumber = myArray[0].Cost;
var highestNumber = myArray[0].Cost;
myArray.forEach(function (keyValue, index, myArray) {
if(index > 0) {
if(keyValue.Cost < lowestNumber){
lowestNumber = keyValue.Cost;
}
if(keyValue.Cost > highestNumber) {
highestNumber = keyValue.Cost;
}
}
});
console.log('lowest number' , lowestNumber);
console.log('highest Number' , highestNumber);
Tristan Reidの答え(es6を使用して+)に追加すると、コールバックを受け入れる関数を作成できます。これには、prev
およびcurr
に適用する演算子が含まれます。
const compare = (arr, key, callback) => arr.reduce((prev, curr) =>
(callback(prev[key], curr[key]) ? prev : curr), {})[key];
// remove `[key]` to return the whole object
次に、単に次を使用して呼び出すことができます。
const costMin = compare(myArray, 'Cost', (a, b) => a < b);
const costMax = compare(myArray, 'Cost', (a, b) => a > b);
これは、lodashのminBy
およびmaxBy
関数で実現できます。
LodashのminBy
およびmaxBy
ドキュメント
_.minBy(array, [iteratee=_.identity])
_.maxBy(array, [iteratee=_.identity])
これらのメソッドは、配列内の各要素に対して呼び出されるiterateeを受け入れ、値がランク付けされる基準を生成します。反復子は、1つの引数(値)で呼び出されます。
var myArray = [
{"ID": 1, "Cost": 200},
{"ID": 2, "Cost": 1000},
{"ID": 3, "Cost": 50},
{"ID": 4, "Cost": 500}
]
const minimumCostItem = _.minBy(myArray, "Cost");
console.log("Minimum cost item: ", minimumCostItem);
// Getting the maximum using a functional iteratee
const maximumCostItem = _.maxBy(myArray, function(entry) {
return entry["Cost"];
});
console.log("Maximum cost item: ", maximumCostItem);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>