Finding the max on collection of objects? - javascript

How can I find the max cell value in a collection of objects using lodash while ignoring one of the keys.
var data = [{
tick: 0,
valueA: 3,
valueB: 2
}, {
tick: 6,
valueA: 6,
valueB: 3
}, {
tick: 12,
valueA: 2,
valueB: 4
}, ...];
I want to find the max tick, this is the row identifier, and the max of all other values. What I have so far is:
var maxTick = _.max(data, 'tick'),
maxValue = _.max(data, function(o) { return _.max(_.values(o))};);
How can I let maxValue ignore the tick data?

Along T Nguyen's line of thought but use _.omit instead of pick that way you only have to omit tick
_.max(data, function(o){_.omit(o, "tick")})

You just need a function which iterates through all elements properties and a list of ignored properties.
Here is a sample:
var findMax = function(list, ignoredFields){
var maxValue = null;
for(var i=0;i<list.length;i++){
for(var prop in list[i]){
if(ignoredFields.indexOf(prop) < 0){
maxValue = maxValue < list[i][prop] ? list[i][prop] : maxValue;
}
}
}
return maxValue;
}
And you execute the function with your data and the list of ignored properties
findMax(data,['tick'])
Update: modified the function to use lodash iterations
var findMax = function(list, ignoredFields){
var maxValue = null;
_.forEach(list, function(element, index) {
var _localMax = _.max(_.omit(element, ignoredFields));
maxValue = maxValue < _localMax ? _localMax : maxValue;
});
return maxValue;
}

Try using _.pick() to pick out all keys except tick then run your max function on that new collection. By the way, your maxValue function doesn't seem right. Are you saying that you want to take the highest scalar valuer in any object, or the object which contains the highest scalar value (except tick)?
UPDATE: Based on your response, try this: http://jsfiddle.net/tonicboy/Xxf9E/1/
var data = [{
tick: 0,
valueA: 3,
valueB: 2
}, {
tick: 6,
valueA: 6,
valueB: 3
}, {
tick: 12,
valueA: 2,
valueB: 4
}],
data2 = [];
_.each(data, function(element, index) {
var values = _.values(_.omit(element, 'tick'));
data2 = data2.concat(values);
});
console.log(data2);
console.log(_.max(data2));

Related

Find max value in object array [duplicate]

This question already has answers here:
Finding the max value of an attribute in an array of objects and return the entire object
(5 answers)
Finding the max value of an attribute in an array of objects
(21 answers)
Closed 4 years ago.
I have object that looks like this:
peaks =
0: {intervalId: 7, time: 1520290800000, value: 54.95125000000001}
1: {intervalId: 7, time: 1520377200000, value: 49.01083333333333}
and so on.
How do I find peak that has Max value?
I tried to do it like this
this.loadPeak = peaks.map(a => Math.max(a.value));
but I just got bunch of peaks array with value (instead of all intervalId, time, value) and not the max value.
**Thank you so much for everyone, every solution was working, sadly can't accept all. **
The main issue with sorting your array, is it causes many needless iterations through your array. This gets drastically slower the bigger your array is, sorting to try and move elements up and down. With reduce(), we can handle this in the minimum amount of steps needed, simply replacing the previous value if the current element's value is greater than the previous:
var peaks = [
{intervalId: 7, time: 1520290800000, value: 54.95125000000001},
{intervalId: 7, time: 1520377200000, value: 49.01083333333333}
];
const maxPeak = peaks.reduce((p, c) => p.value > c.value ? p : c);
console.log(maxPeak);
You could spread only the value value for Math.max.
var peaks = [{ intervalId: 7, time: 1520290800000, value: 54.95125000000001 }, { intervalId: 7, time: 1520377200000, value: 49.01083333333333 }]
max = Math.max(...peaks.map(({ value }) => value)),
object = peaks.find(({ value }) => value === max);
console.log(max);
console.log(object);
The simple way is just to use a loop:
this.loadPeak = null;
for (const peak of peaks) {
if (!this.loadPeak || peak.value > this.loadPeak.value) {
this.loadPeak = peak;
}
}
Live Example:
const peaks = [
{intervalId: 7, time: 1520290800000, value: 54.95125000000001},
{intervalId: 7, time: 1520377200000, value: 49.01083333333333}
];
let loadPeak = null;
for (const peak of peaks) {
if (!loadPeak || peak.value > loadPeak.value) {
loadPeak = peak;
}
}
console.log(loadPeak);
As with nearly any array operation, you can shoe-horn it into a reduce call if you like:
this.loadPeak = peaks.reduce((maxPeak, peak) => !maxPeak || maxPeak.value < peak.value ? peak : maxPeak, null);
const peaks = [
{intervalId: 7, time: 1520290800000, value: 54.95125000000001},
{intervalId: 7, time: 1520377200000, value: 49.01083333333333}
];
const loadPeak = peaks.reduce((maxPeak, peak) => !maxPeak || maxPeak.value < peak.value ? peak : maxPeak, null);
console.log(loadPeak);
I should have realized earlier this was a duplicate question. I've found the dupetarget, marked it, and made this a CW answer.
You can sort your peaks in descending order of value, then pick the first of the sorted array.
let peaks = [{
intervalId: 7,
time: 1520290800000,
value: 54.95125000000001
},
{
intervalId: 7,
time: 1520377200000,
value: 49.01083333333333
}
]
let sortedPeaks = peaks.sort((a, b) => b.value - a.value)
let loadPeak = sortedPeaks[0];
console.log(loadPeak);

sum up object properties in array of objects into a single object Lodash

I have been trying to get this right and was having issues so figured i should ask ppl with more experience. I have an array of objects lets say called items, and I need to sum up some of the properties across different objects in the array and sum them up those at the end. The user can make a few selections and i need to only sum up the only the chosen properties in the array they give me so i thought maybe to use the _.pick function in lodash. If possible i would like to do that in one loop since the items array could have upto a 1000 items. Here is an example:
var items = [
{'lightBlue':4, 'darkBlue':2, 'red':4, 'orange':6, 'purple':7},
{'lightBlue':6, 'darkBlue':5, 'red':1, 'orange':2, 'purple':3},
{'lightBlue':2, 'darkBlue':4, 'red':3, 'orange':4, 'purple':9}
]
var userSelectedColors = ['lightBlue', 'darkBlue'];
What I want to see is all the blue's summed up like:
var summedUp = [{'lightBlue':12, 'darkBlue':11}];
Then sum up the results to get the total no
var totalCount = 23
Whats the best and performant way to get this in lodash. The array of userSelectedColors could be 1 or any combination of the colors.
Please provide an example, thanks your helps appreciated!
Use _.sumBy
var totalCount = _.sumBy(userSelectedColors, _.partial(_.sumBy, items));
var items = [
{ 'lightBlue': 4, 'darkBlue': 2, 'red': 4, 'orange': 6, 'purple': 7 },
{ 'lightBlue': 6, 'darkBlue': 5, 'red': 1, 'orange': 2, 'purple': 3 },
{ 'lightBlue': 2, 'darkBlue': 4, 'red': 3, 'orange': 4, 'purple': 9 }
], userSelectedColors = ['lightBlue', 'darkBlue'];
var totalCount = _.sumBy(userSelectedColors, _.partial(_.sumBy, items));
console.log(totalCount);
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.min.js"></script>
Expanded, that looks like:
var totalCount = _.sumBy(userSelectedColors, function(prop) {
return _.sumBy(items, prop);
});
Without Lodash, a more performant solution would be something like this:
var totalCount = items.reduce(function(total, obj) {
return total + userSelectedColors.reduce(function(total, prop) {
return total + obj[prop];
}, 0);
}, 0);
var items = [
{ 'lightBlue': 4, 'darkBlue': 2, 'red': 4, 'orange': 6, 'purple': 7 },
{ 'lightBlue': 6, 'darkBlue': 5, 'red': 1, 'orange': 2, 'purple': 3 },
{ 'lightBlue': 2, 'darkBlue': 4, 'red': 3, 'orange': 4, 'purple': 9 }
], userSelectedColors = ['lightBlue', 'darkBlue'];
var totalCount = items.reduce(function(total, obj) {
return total + userSelectedColors.reduce(function(total, prop) {
return total + obj[prop];
}, 0);
}, 0);
console.log(totalCount);
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.min.js"></script>
In terms of efficiency, I believe this is hard to beat, since it only iterates once through the array, but it's not quite as succinct as an approach like the one #4castle took. (Also, for only 1000 items, you're never going to notice the performance difference anyway.)
var items = [
{'lightBlue':4, 'darkBlue':2, 'red':4, 'orange':6, 'purple':7},
{'lightBlue':6, 'darkBlue':5, 'red':1, 'orange':2, 'purple':3},
{'lightBlue':2, 'darkBlue':4, 'red':3, 'orange':4, 'purple':9}
]
var userSelectedColors = ['lightBlue', 'darkBlue'];
var sums = {};
_.each(items, function (item) {
_.each(userSelectedColors, function (color) {
sums[color] = (sums[color] || 0) + item[color];
});
});
console.log('Summary: ', sums);
console.log('Grand total: ', _.sum(_.values(sums)));
Output:
Summary: { lightBlue: 12, darkBlue: 11 }
Grand total: 23
Getting the Summary
var summary = userSelectedColors.map(c => ({ [c]: _.sumBy(items, c)}))
Total
var total = _.sum(Object.values(summary))

Javascript: Most Efficient Way of Summing Multiple Arrays by Key

I have a JSON object returned from a web service, which is an array of objects. I need to add the "data" arrays together to form a summed array. The JSON response looks like this:
[
{
"data":[
0,3,8,2,5
],
"someKey":"someValue"
},
{
"data":[
3,13,1,0,5
],
"someKey":"someOtherValue"
}
]
There could be N amount of objects in the array. The desired output for the above example would be:
[3, 16, 9, 2, 10]
I was intending on creating an empty array variable (var arr), then looping over the objects, and for each object, loop through the "data" key and for each key increment the corresponding key in arr by the value.
Is there a more efficient way of doing this using some sort of merge function?
How about this, I believe it should work for all cases.
var data = [{
"data": [
0, 3, 8, 2, 5
],
"someKey": "someValue"
}, {
"data": [
3, 13, 1, 0, 5
],
"someKey": "someOtherValue"
}];
var datas = data.reduce(function(a, b) {
b.data.forEach(function(x, i) {
a[i] = a[i] || 0;
a[i] += x;
});
return a;
}, []);
console.log(datas);
If every object has the same data length, you can try with:
var input; // Your input data
var output = [];
for (var i = 0; i < input[0].data.length; i++) {
output[i] = input.reduce(function(prev, item) {
return +(item.data[i]) + prev;
}, 0);
}
console.log(output);
// [3, 16, 9, 2, 10]
If every object has different data size:
var input; // Your input data
var i = 0, output = [];
while (true) {
var outOfIndex = true;
var sum = input.reduce(function(prev, item) {
if (item.data[i] !== undefined) {
outOfIndex = false;
}
return +(item.data[i]) + prev;
}, 0);
if (outOfIndex) {
break;
}
output[i++] = sum;
}
console.log(output);
// [3, 16, 9, 2, 10]
Slightly less imperative solution:
//zip takes two arrays and combines them per the fn argument
function zip(left, right, fn) {
var shorter = (right.length > left.length) ? left : right;
return shorter.map(function(value, i) {
return fn(left[i], right[i]);
});
}
//assuming arr is your array of objects. Because were using
//zip, map, and reduce, it doesn't matter if the length of the
//data array changes
var sums = arr
.map(function(obj) { return obj.data; })
.reduce(function(accum, array) {
//here we want to combine the running totals w/the current data
return zip(accum, array, function(l, r) { return l + r; });
});

Sort object by value

So here's the object:
As you can see, the last amount(2000) is lower than 10000 but it's still at the end. I'm trying to display the elements sorted by amount. I know that I have to convert the object to array and use sort on it, but don't have an idea how can I do this properly.
EDIT: I've tried something like this without any success:
var packs_array = [];
jQuery.each(json.purchase_packs, function(i, pack) {
packs_array.push(pack);
});
packs_array.sort();
var packs = {
0: { amount: 2000 },
3: { amount: 1000 },
5: { amount: 50 }
};
var sortedPacks = Object.keys(packs)
.map(function (id) {
packs[id].id = parseInt(id, 10);
return packs[id];
})
.sort(function (a, b) {
return a.amount - b.amount;
});
console.log(sortedPacks); // => [{"amount":50,"id":5},{"amount":1000,"id":3},{"amount":2000,"id":0}]
To do this, you need to convert your object into an array first...
var arr = $.map(json.purchase_packs, function(v) { return v; });
... then sort this array with a custom sorter function:
arr.sort(function(a, b) {
return a.amount - b.amount;
});
Demo. Note that sorting is in-place operation (i.e., arr.sort alters an existing object).
JavaScript sort() function works with list elements as strings by default. You should specify sort function to sort other value types:
var l = [1, 5, 12, 127, 12, 3, 9];
l.sort(function(a,b){return a-b});
=> [ 1, 3, 5, 9, 12, 12, 127 ]
Source

Obtain smallest value from array in Javascript?

Array justPrices has values such as:
[0] = 1.5
[1] = 4.5
[2] = 9.9.
How do I return the smallest value in the array?
The tersest expressive code to find the minimum value is probably rest parameters:
const arr = [14, 58, 20, 77, 66, 82, 42, 67, 42, 4]
const min = Math.min(...arr)
console.log(min)
Rest parameters are essentially a convenient shorthand for Function.prototype.apply when you don't need to change the function's context:
var arr = [14, 58, 20, 77, 66, 82, 42, 67, 42, 4]
var min = Math.min.apply(Math, arr)
console.log(min)
This is also a great use case for Array.prototype.reduce:
const arr = [14, 58, 20, 77, 66, 82, 42, 67, 42, 4]
const min = arr.reduce((a, b) => Math.min(a, b))
console.log(min)
It may be tempting to pass Math.min directly to reduce, however the callback receives additional parameters:
callback (accumulator, currentValue, currentIndex, array)
In this particular case it may be a bit verbose. reduce is particularly useful when you have a collection of complex data that you want to aggregate into a single value:
const arr = [{name: 'Location 1', distance: 14}, {name: 'Location 2', distance: 58}, {name: 'Location 3', distance: 20}, {name: 'Location 4', distance: 77}, {name: 'Location 5', distance: 66}, {name: 'Location 6', distance: 82}, {name: 'Location 7', distance: 42}, {name: 'Location 8', distance: 67}, {name: 'Location 9', distance: 42}, {name: 'Location 10', distance: 4}]
const closest = arr.reduce(
(acc, loc) =>
acc.distance < loc.distance
? acc
: loc
)
console.log(closest)
And of course you can always use classic iteration:
var arr,
i,
l,
min
arr = [14, 58, 20, 77, 66, 82, 42, 67, 42, 4]
min = Number.POSITIVE_INFINITY
for (i = 0, l = arr.length; i < l; i++) {
min = Math.min(min, arr[i])
}
console.log(min)
...but even classic iteration can get a modern makeover:
const arr = [14, 58, 20, 77, 66, 82, 42, 67, 42, 4]
let min = Number.POSITIVE_INFINITY
for (const value of arr) {
min = Math.min(min, value)
}
console.log(min)
Jon Resig illustrated in this article how this could be achieved by extending the Array prototype and invoking the underlying Math.min method which unfortunately doesn't take an array but a variable number of arguments:
Array.min = function( array ){
return Math.min.apply( Math, array );
};
and then:
var minimum = Array.min(array);
I find that the easiest way to return the smallest value of an array is to use the Spread Operator on Math.min() function.
return Math.min(...justPrices);
//returns 1.5 on example given
The page on MDN helps to understand it better: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/min
A little extra:
This also works on Math.max() function
return Math.max(...justPrices);
//returns 9.9 on example given.
Hope this helps!
Update: use Darin's / John Resig answer, just keep in mind that you dont need to specifiy thisArg for min, so Math.min.apply(null, arr) will work just fine.
or you can just sort the array and get value #1:
[2,6,7,4,1].sort()[0]
[!] But without supplying custom number sorting function, this will only work in one, very limited case: positive numbers less than 10. See how it would break:
var a = ['', -0.1, -2, -Infinity, Infinity, 0, 0.01, 2, 2.0, 2.01, 11, 1, 1e-10, NaN];
// correct:
a.sort( function (a,b) { return a === b ? 0 : a < b ? -1: 1} );
//Array [NaN, -Infinity, -2, -0.1, 0, "", 1e-10, 0.01, 1, 2, 2, 2.01, 11, Infinity]
// incorrect:
a.sort();
//Array ["", -0.1, -2, -Infinity, 0, 0.01, 1, 11, 1e-10, 2, 2, 2.01, Infinity, NaN]
And, also, array is changed in-place, which might not be what you want.
Imagine you have this array:
var arr = [1, 2, 3];
ES6 way:
var min = Math.min(...arr); //min=1
ES5 way:
var min = Math.min.apply(null, arr); //min=1
If you using D3.js, there is a handy function which does the same, but will ignore undefined values and also check the natural order:
d3.max(array[, accessor])
Returns the maximum value in the given array using natural order. If
the array is empty, returns undefined. An optional accessor function
may be specified, which is equivalent to calling array.map(accessor)
before computing the maximum value.
Unlike the built-in Math.max, this method ignores undefined values;
this is useful for ignoring missing data. In addition, elements are
compared using natural order rather than numeric order. For example,
the maximum of the strings [“20”, “3”] is “3”, while the maximum of
the numbers [20, 3] is 20.
And this is the source code for D3 v4:
export default function(values, valueof) {
var n = values.length,
i = -1,
value,
max;
if (valueof == null) {
while (++i < n) { // Find the first comparable value.
if ((value = values[i]) != null && value >= value) {
max = value;
while (++i < n) { // Compare the remaining values.
if ((value = values[i]) != null && value > max) {
max = value;
}
}
}
}
}
else {
while (++i < n) { // Find the first comparable value.
if ((value = valueof(values[i], i, values)) != null && value >= value) {
max = value;
while (++i < n) { // Compare the remaining values.
if ((value = valueof(values[i], i, values)) != null && value > max) {
max = value;
}
}
}
}
}
return max;
}
ES6 is the way of the future.
arr.reduce((a, b) => Math.min(a, b));
I prefer this form because it's easily generalized for other use cases
var array =[2,3,1,9,8];
var minvalue = array[0];
for (var i = 0; i < array.length; i++) {
if(array[i]<minvalue)
{
minvalue = array[i];
}
}
console.log(minvalue);
Possibly an easier way?
Let's say justPrices is mixed up in terms of value, so you don't know where the smallest value is.
justPrices[0] = 4.5
justPrices[1] = 9.9
justPrices[2] = 1.5
Use sort.
justPrices.sort();
It would then put them in order for you. (Can also be done alphabetically.) The array then would be put in ascending order.
justPrices[0] = 1.5
justPrices[1] = 4.5
justPrices[2] = 9.9
You can then easily grab by the first index.
justPrices[0]
I find this is a bit more useful than what's proposed above because what if you need the lowest 3 numbers as an example? You can also switch which order they're arranged, more info at http://www.w3schools.com/jsref/jsref_sort.asp
function smallest(){
if(arguments[0] instanceof Array)
arguments = arguments[0];
return Math.min.apply( Math, arguments );
}
function largest(){
if(arguments[0] instanceof Array)
arguments = arguments[0];
return Math.max.apply( Math, arguments );
}
var min = smallest(10, 11, 12, 13);
var max = largest([10, 11, 12, 13]);
console.log("Smallest: "+ min +", Largest: "+ max);
I think I have an easy-to-understand solution for this, using only the basics of javaScript.
function myFunction() {
var i = 0;
var smallestNumber = justPrices[0];
for(i = 0; i < justPrices.length; i++) {
if(justPrices[i] < smallestNumber) {
smallestNumber = justPrices[i];
}
}
return smallestNumber;
}
The variable smallestNumber is set to the first element of justPrices, and the for loop loops through the array (I'm just assuming that you know how a for loop works; if not, look it up). If an element of the array is smaller than the current smallestNumber (which at first is the first element), it will replace it's value. When the whole array has gone through the loop, smallestNumber will contain the smallest number in the array.
Here’s a variant of Darin Dimitrov’s answer that doesn’t modify the Array prototype:
const applyToArray = (func, array) => func.apply(Math, array)
applyToArray(Math.min, [1,2,3,4]) // 1
applyToArray(Math.max, [1,2,3,4]) // 4
function tinyFriends() {
let myFriends = ["Mukit", "Ali", "Umor", "sabbir"]
let smallestFridend = myFriends[0];
for (i = 0; i < myFriends.length; i++) {
if (myFriends[i] < smallestFridend) {
smallestFridend = myFriends[i];
}
}
return smallestFridend
}
A super-easy way to find the smallest value would be
Array.prototype.min = function(){
return Math.min.apply(Math,this);
};
To call the function, just use the name of the array and add .min()
Array.prototype.min = function(){
return Math.min.apply(Math,this);
};
var arr = [12,56,126,-1,5,15];
console.log( arr.min() );
If you are using Underscore or Lodash you can get the minimal value using this kind of simple functional pipeline
_.chain([7, 6, -1, 3, 2]).sortBy().first().value()
// -1
You also have the .min function
_.min([7, 6, -1, 3, 2])
// -1
Here is code that will detect the lowest value in an array of numbers.
//function for finding smallest value in an array
function arrayMin(array){
var min = array[0];
for(var i = 0; i < array.length; i++){
if(min < array[i]){
min = min;
}else if (min > array[i]){
min = array[i + 1];
}else if (min == array[i]){
min = min;
}
}
return min;
};
call it in this way:
var fooArray = [1,10,5,2];
var foo = arrayMin(fooArray);
(Just change the second else if result from: min = min to min = array[i]
if you want numbers which reach the smallest value to replace the original number.)
Here is a recursive way on how to do it using ternary operators both for the recursion and decision whether you came across a min number or not.
const findMin = (arr, min, i) => arr.length === i ? min :
findMin(arr, min = arr[i] < min ? arr[i] : min, ++i)
Code snippet:
const findMin = (arr, min, i) => arr.length === i ? min :
findMin(arr, min = arr[i] < min ? arr[i] : min, ++i)
const arr = [5, 34, 2, 1, 6, 7, 9, 3];
const min = findMin(arr, arr[0], 0)
console.log(min);
You can use min method in Math object!
const abc = [50, 35, -25, -6, 91];
function findMin(args) {
return Math.min(...args);
}
console.log(findMin(abc));
For anyone out there who needs this I just have a feeling.
(Get the smallest number with multi values in the array)
Thanks to Akexis answer.
if you have let's say an array of
Distance and ID and ETA in minutes
So you do push maybe in for loop or something
Distances.push([1.3, 1, 2]); // Array inside an array.
And then when It finishes, do a sort
Distances.sort();
So this will sort upon the first thing which is Distance here.
Now we have the closest or the least is the first you can do
Distances[0] // The closest distance or the smallest number of distance. (array).

Categories