Mam tablicę obiektów i chcę porównać te obiekty na określonej właściwości obiektu. Oto moja tablica:
var myArray = [
{"ID": 1, "Cost": 200},
{"ID": 2, "Cost": 1000},
{"ID": 3, "Cost": 50},
{"ID": 4, "Cost": 500}
]
Chciałbym skupić się konkretnie na „koszcie” i uzyskać minimalną i maksymalną wartość. Zdaję sobie sprawę, że mogę po prostu pobrać wartości kosztów i przenieść je do tablicy javascript, a następnie uruchomić Fast JavaScript Max / Min .
Czy jest jednak prostszy sposób na to, pomijając krok tablicy w środku i bezpośrednio wyłączając właściwości obiektów (w tym przypadku „Koszt”)?
javascript
arrays
compare
firedrawndagger
źródło
źródło
lowest=highest=myArray[0]
a następnie rozpocząć pętlę od 1.myArray[0].Cost
. Ale jeśli nie ma pierwszego elementu, zostanie zgłoszony błąd. Potrzebna jest więc dodatkowa kontrola, prawdopodobnie cofająca niewielki wzrost wydajności.var lowestObject; for (...)
iif (tmp < lowest) { lowestObject = myArray[i]; lowest = tmp; }
Redukcja jest dobra w przypadku takich rzeczy: do wykonywania zagregowanych operacji (takich jak min, max, avg itp.) Na tablicy obiektów i zwracania pojedynczego wyniku:
myArray.reduce(function(prev, curr) { return prev.Cost < curr.Cost ? prev : curr; });
... lub możesz zdefiniować tę funkcję wewnętrzną za pomocą składni funkcji ES6:
Jeśli chcesz być uroczy, możesz dołączyć to do tablicy:
Array.prototype.hasMin = function(attrib) { return (this.length && this.reduce(function(prev, curr){ return prev[attrib] < curr[attrib] ? prev : curr; })) || null; }
Teraz możesz po prostu powiedzieć:
myArray.hasMin('ID') // result: {"ID": 1, "Cost": 200} myArray.hasMin('Cost') // result: {"ID": 3, "Cost": 50} myEmptyArray.hasMin('ID') // result: null
Pamiętaj, że jeśli zamierzasz tego użyć, nie ma pełnej kontroli dla każdej sytuacji. Jeśli przekażesz tablicę typów pierwotnych, zakończy się niepowodzeniem. Jeśli sprawdzisz właściwość, która nie istnieje, lub jeśli nie wszystkie obiekty zawierają tę właściwość, otrzymasz ostatni element. Ta wersja jest trochę bardziej nieporęczna, ale ma następujące kontrole:
Array.prototype.hasMin = function(attrib) { const checker = (o, i) => typeof(o) === 'object' && o[i] return (this.length && this.reduce(function(prev, curr){ const prevOk = checker(prev, attrib); const currOk = checker(curr, attrib); if (!prevOk && !currOk) return {}; if (!prevOk) return curr; if (!currOk) return prev; return prev[attrib] < curr[attrib] ? prev : curr; })) || null; }
źródło
prev.Cost
będzie niezdefiniowany? Czy inicjuje jako 0?Użyj
sort
, jeśli nie obchodzi Cię modyfikacja tablicy.myArray.sort(function (a, b) { return a.Cost - b.Cost }) var min = myArray[0], max = myArray[myArray.length - 1]
źródło
myArray
, czego nie można się spodziewać.O(nlog(n))
O(n)
Użyj
Math
funkcji i wyodrębnij żądane wartościmap
.Oto 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
AKTUALIZACJA:
Jeśli chcesz używać ES6:
var min = Math.min.apply(null, myArray.map(item => item.Cost)), max = Math.max.apply(null, myArray.map(item => item.Cost));
źródło
apply
. Po prostu powiedz -Math.min(...myArray.map(o => o.Cost))
aby znaleźć minimum iMath.max(...myArray.map(o => o.Cost))
znaleźć maksimum.Myślę, że odpowiedź Rob W za to bardzo słuszna (+1), ale tylko dla zabawy: jeśli chcesz być „mądry”, to mógłby zrobić coś takiego:
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"));
lub jeśli masz głęboko zagnieżdżoną strukturę, możesz uzyskać trochę bardziej funkcjonalną i wykonać następujące czynności:
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; }));
Można je łatwo curry w bardziej przydatne / specyficzne formy.
źródło
dla Max
Math.max.apply(Math, myArray.map(a => a.Cost));
na min
Math.min.apply(Math, myArray.map(a => a.Cost));
źródło
Try (
a
to tablica,f
to pole do porównania)let max= (a,f)=> a.reduce((m,x)=> m[f]>x[f] ? m:x); let min= (a,f)=> a.reduce((m,x)=> m[f]<x[f] ? m:x);
Pokaż fragment kodu
let max= (a,f)=> a.reduce((m,x)=> m[f]>x[f] ? m:x); let min= (a,f)=> a.reduce((m,x)=> m[f]<x[f] ? m:x); // TEST var myArray = [ {"ID": 1, "Cost": 200}, {"ID": 2, "Cost": 1000}, {"ID": 3, "Cost": 50}, {"ID": 4, "Cost": 500} ] console.log('Max Cost', max(myArray, 'Cost')); console.log('Min Cost', min(myArray, 'Cost')); console.log('Max ID', max(myArray, 'ID')); console.log('Min ID', min(myArray, 'ID'));
źródło
Korzystając z Array.prototype.reduce () , możesz podłączyć funkcje komparatora w celu określenia wartości min, max itd. W tablicy.
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;
źródło
Korzystanie
Math.min
iMath.max
:var myArray = [ { id: 1, cost: 200}, { id: 2, cost: 1000}, { id: 3, cost: 50}, { id: 4, cost: 500} ] var min = Math.min(...myArray.map(item => item.cost)); var max = Math.max(...myArray.map(item => item.cost)); console.log("min: " + min); console.log("max: " + max);
źródło
To lepsze rozwiązanie
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);
źródło
Dodając do odpowiedzi Tristana Reida (+ używając es6), możesz stworzyć funkcję akceptującą wywołanie zwrotne, która będzie zawierała operator, który chcesz zastosować do
prev
icurr
:const compare = (arr, key, callback) => arr.reduce((prev, curr) => (callback(prev[key], curr[key]) ? prev : curr), {})[key]; // remove `[key]` to return the whole object
Następnie możesz po prostu zadzwonić za pomocą:
const costMin = compare(myArray, 'Cost', (a, b) => a < b); const costMax = compare(myArray, 'Cost', (a, b) => a > b);
źródło
Można to osiągnąć za pomocą lodash
minBy
imaxBy
funkcji.Lodash
minBy
imaxBy
dokumentacjaRozwiązanie
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>
źródło
1, natywny sposób skryptu java
2, najpierw sortuj obiekt, a następnie łatwo uzyskasz min max z posortowanego obiektu
//first approach var myArray = [ {"ID": 1, "Cost": 200}, {"ID": 2, "Cost": 1000}, {"ID": 3, "Cost": 50}, {"ID": 4, "Cost": 500} ] var t1 = performance.now();; let max=Math.max.apply(Math, myArray.map(i=>i.Cost)) let min=Math.min.apply(Math, myArray.map(i=>i.Cost)) var t2 = performance.now();; console.log("native fuction took " + (t2 - t1) + " milliseconds."); console.log("max Val:"+max) console.log("min Val:"+min) // Second approach: function sortFunc (a, b) { return a.Cost - b.Cost } var s1 = performance.now();; sortedArray=myArray.sort(sortFunc) var minBySortArray = sortedArray[0], maxBySortArray = sortedArray[myArray.length - 1] var s2 = performance.now();; console.log("sort funciton took " + (s2 - s1) + " milliseconds."); console.log("max ValBySortArray :"+max) console.log("min Val BySortArray:"+min)
źródło
Aby uzyskać zwięzłe, nowoczesne rozwiązanie, można wykonać
reduce
operację na tablicy, śledząc bieżące wartości minimalne i maksymalne, więc tablica jest iterowana tylko raz (co jest optymalne).let [min, max] = myArray.reduce(([prevMin,prevMax], {Cost})=> [Math.min(prevMin, Cost), Math.max(prevMax, Cost)], [Infinity, -Infinity]);
Próbny:
Pokaż fragment kodu
var myArray = [ {"ID": 1, "Cost": 200}, {"ID": 2, "Cost": 1000}, {"ID": 3, "Cost": 50}, {"ID": 4, "Cost": 500} ] let [min, max] = myArray.reduce(([prevMin,prevMax], {Cost})=> [Math.min(prevMin, Cost), Math.max(prevMax, Cost)], [Infinity, -Infinity]); console.log("Min cost:", min); console.log("Max cost:", max);
źródło
Kolejny, podobny do odpowiedzi Kennebeca, ale wszystko w jednym wierszu:
maxsort = myArray.slice(0).sort(function (a, b) { return b.ID - a.ID })[0].ID;
źródło
Możesz użyć wbudowanego obiektu Array, aby zamiast tego użyć Math.max / Math.min:
var arr = [1,4,2,6,88,22,344]; var max = Math.max.apply(Math, arr);// return 344 var min = Math.min.apply(Math, arr);// return 1
źródło