Find Min/Max Values from List grouped by Object Identifier

I'm trying to find the largest and smallest value in an group of items with same attributes. For example from the screenshot, the max value for crop: 18157 would be 1.77 and the smallest 1.68

JsFiddle: https://jsfiddle.net/kf3qhsge/

var myCrops = new Object();

for(i=0;i<crops.length;i++){
    if(crops[i]==crops[i+1]){
        var c = crops[i];
        var n = values[i];
        myCrops[i] = {"crop":c,"value":n};
    }

} 

enter image description here

Answers:

Answer

This is simpler in both time and space complexity than the other solutions* here:

var crops  = [18002, 18154, 18154, 18155, 18155, 18155, 18156, 18156, 18156, 18156, 18157, 18157, 18157, 18157, 18157, 18158, 18158, 18158, 18158, 18158, 18158, 18159, 18159, 18159, 18159, 18159, 18159, 18159, 18160, 18160, 18160, 18160, 18160, 18160, 18160, 18160, 18160, 18161, 18161, 18161, 18161, 18161, 18161, 18161, 18161, 18161, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18170, 18170, 18170, 18170, 18170, 18170, 18170, 18170, 18170, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18176, 18176, 18176, 18176, 18176];
var values = [1.69, 1.65, 1.75, 1.7, 1.7, 1.78, 1.69, 1.62, 1.75, 1.74, 1.7, 1.72, 1.68, 1.77, 1.7, 1.62, 1.74, 1.69, 1.82, 1.68, 1.64, 1.66, 1.74, 1.57, 1.7, 1.7, 1.6, 1.66, 1.72, 1.47, 1.52, 1.7, 1.63, 1.67, 1.69, 1.7, 1.51, 1.49, 1.58, 1.63, 1.66, 1.68, 1.39, 1.71, 1.61, 1.62, 1.41, 1.52, 1.46, 1.41, 1.61, 1.65, 1.36, 1.59, 1.65, 1.64, 1.72, 1.52, 1.35, 1.49, 1.65, 1.32, 1.37, 1.69, 1.62, 1.63, 1.7, 1.72, 1.7, 1.3, 1.47, 1.56, 1.5, 1.67, 1.41, 1.73, 1.71, 1.67, 1.58, 1.73, 1.56, 1.66, 1.73, 1.57, 1.69, 1.58, 1.73, 1.47, 1.7, 1.8, 1.61, 1.77, 1.79, 1.63, 1.56, 1.58, 1.59, 1.84, 1.64, 1.77, 1.63, 1.7, 1.76, 1.73, 1.83, 1.63, 1.44, 1.32, 1.74, 1.46, 1.57, 1.67, 1.4, 1.64, 1.69, 1.58, 1.76, 1.69, 1.58, 1.72, 1.43, 1.7, 1.34, 1.69, 1.64, 1.6, 1.68, 1.5, 1.69, 1.5, 1.76, 1.47, 1.7, 1.63, 1.49, 1.48, 1.15, 1.59, 1.65, 1.6, 1.46, 1.43, 1.52, 1.55, 1.63, 1.41, 1.66, 1.62, 1.66, 1.66, 1.68, 1.63, 1.66, 1.59, 1.34, 1.67, 1.68, 1.46, 1.66, 1.77, 1.71, 1.71, 1.6, 1.47, 1.71, 1.75, 1.6, 1.58, 1.35, 1.72, 1.77, 1.68, 1.64, 1.71, 1.59, 1.63, 1.74, 1.39, 1.59, 1.71, 1.72, 1.25, 1.65, 1.7, 1.67, 1.71, 1.67, 1.49, 1.69, 1.36, 1.53, 1.73, 1.57, 1.58, 1.7, 1.61, 1.61, 1.7, 1.62, 1.69];

var myCrops = {};
for (i = 0; i < crops.length; i++) {
    
    var c = crops[i];
    if (c in myCrops) {

        var v = myCrops[c];

        if (values[i] > v.max)
            myCrops[c].max = values[i];
        if (values[i] < v.min)
            myCrops[c].min = values[i];
    }
    else {
        myCrops[c] = { min: values[i], max: values[i] };
    } 
}


console.log("Min/Max for crop 18157:\n", myCrops[18157]);

console.log("Min/Max for all crops:\n", myCrops);

Outputs for myCrops[18157]:

{min: 1.68, max: 1.77}

  • There were other solutions here when I posted this which were not as efficient, and were deleted by the posters after I posted. Ironically before they deleted their answers they downvoted mine.
Answer

You can use reduce

Here idea is

  • Loop through crops and use it as key for op object.
  • For each value of crops we check whether the key is already in op object or not if it is already there we change the max and min value based on conditions.
  • If it is not than we add a new key with proper values.

var crops  = [18002, 18154, 18154, 18155, 18155, 18155, 18156, 18156, 18156, 18156, 18157, 18157, 18157, 18157, 18157, 18158, 18158, 18158, 18158, 18158, 18158, 18159, 18159, 18159, 18159, 18159, 18159, 18159, 18160, 18160, 18160, 18160, 18160, 18160, 18160, 18160, 18160, 18161, 18161, 18161, 18161, 18161, 18161, 18161, 18161, 18161, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18170, 18170, 18170, 18170, 18170, 18170, 18170, 18170, 18170, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18176, 18176, 18176, 18176, 18176];
var values = [1.69, 1.65, 1.75, 1.7, 1.7, 1.78, 1.69, 1.62, 1.75, 1.74, 1.7, 1.72, 1.68, 1.77, 1.7, 1.62, 1.74, 1.69, 1.82, 1.68, 1.64, 1.66, 1.74, 1.57, 1.7, 1.7, 1.6, 1.66, 1.72, 1.47, 1.52, 1.7, 1.63, 1.67, 1.69, 1.7, 1.51, 1.49, 1.58, 1.63, 1.66, 1.68, 1.39, 1.71, 1.61, 1.62, 1.41, 1.52, 1.46, 1.41, 1.61, 1.65, 1.36, 1.59, 1.65, 1.64, 1.72, 1.52, 1.35, 1.49, 1.65, 1.32, 1.37, 1.69, 1.62, 1.63, 1.7, 1.72, 1.7, 1.3, 1.47, 1.56, 1.5, 1.67, 1.41, 1.73, 1.71, 1.67, 1.58, 1.73, 1.56, 1.66, 1.73, 1.57, 1.69, 1.58, 1.73, 1.47, 1.7, 1.8, 1.61, 1.77, 1.79, 1.63, 1.56, 1.58, 1.59, 1.84, 1.64, 1.77, 1.63, 1.7, 1.76, 1.73, 1.83, 1.63, 1.44, 1.32, 1.74, 1.46, 1.57, 1.67, 1.4, 1.64, 1.69, 1.58, 1.76, 1.69, 1.58, 1.72, 1.43, 1.7, 1.34, 1.69, 1.64, 1.6, 1.68, 1.5, 1.69, 1.5, 1.76, 1.47, 1.7, 1.63, 1.49, 1.48, 1.15, 1.59, 1.65, 1.6, 1.46, 1.43, 1.52, 1.55, 1.63, 1.41, 1.66, 1.62, 1.66, 1.66, 1.68, 1.63, 1.66, 1.59, 1.34, 1.67, 1.68, 1.46, 1.66, 1.77, 1.71, 1.71, 1.6, 1.47, 1.71, 1.75, 1.6, 1.58, 1.35, 1.72, 1.77, 1.68, 1.64, 1.71, 1.59, 1.63, 1.74, 1.39, 1.59, 1.71, 1.72, 1.25, 1.65, 1.7, 1.67, 1.71, 1.67, 1.49, 1.69, 1.36, 1.53, 1.73, 1.57, 1.58, 1.7, 1.61, 1.61, 1.7, 1.62, 1.69];

let op = crops.reduce((op,inp,index)=>{
  let min = op[inp] && op[inp].min
  let max = op[inp] && op[inp].max
  let value = values[index]
  if(op[inp]){
    op[inp].min = value < min ? value : min
    op[inp].max = value > max ? value : max
  } else {
    op[inp] = {crop:inp,min:value,max:value}
  }
  return op
},{})

console.log(op)

Answer

We can divide the task in two steps:
1. obtain the values corresponding to a certain crop
2. obtain the minimum and maximum among those values.

For the first step, you can filter the values array by looking in the corresponding index in the crops array. For this, we profit that the function passed to filter admits the index as second parameter. For the second one, an alternative to reduce is to use the built-in Math.min / Math.max functions.

Namely:

var crops = [18002, 18154, 18154, 18155, 18155, 18155, 18156, 18156, 18156, 18156, 18157, 18157, 18157, 18157, 18157, 18158, 18158, 18158, 18158, 18158, 18158, 18159, 18159, 18159, 18159, 18159, 18159, 18159, 18160, 18160, 18160, 18160, 18160, 18160, 18160, 18160, 18160, 18161, 18161, 18161, 18161, 18161, 18161, 18161, 18161, 18161, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18170, 18170, 18170, 18170, 18170, 18170, 18170, 18170, 18170, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18176, 18176, 18176, 18176, 18176];
var values = [1.69, 1.65, 1.75, 1.7, 1.7, 1.78, 1.69, 1.62, 1.75, 1.74, 1.7, 1.72, 1.68, 1.77, 1.7, 1.62, 1.74, 1.69, 1.82, 1.68, 1.64, 1.66, 1.74, 1.57, 1.7, 1.7, 1.6, 1.66, 1.72, 1.47, 1.52, 1.7, 1.63, 1.67, 1.69, 1.7, 1.51, 1.49, 1.58, 1.63, 1.66, 1.68, 1.39, 1.71, 1.61, 1.62, 1.41, 1.52, 1.46, 1.41, 1.61, 1.65, 1.36, 1.59, 1.65, 1.64, 1.72, 1.52, 1.35, 1.49, 1.65, 1.32, 1.37, 1.69, 1.62, 1.63, 1.7, 1.72, 1.7, 1.3, 1.47, 1.56, 1.5, 1.67, 1.41, 1.73, 1.71, 1.67, 1.58, 1.73, 1.56, 1.66, 1.73, 1.57, 1.69, 1.58, 1.73, 1.47, 1.7, 1.8, 1.61, 1.77, 1.79, 1.63, 1.56, 1.58, 1.59, 1.84, 1.64, 1.77, 1.63, 1.7, 1.76, 1.73, 1.83, 1.63, 1.44, 1.32, 1.74, 1.46, 1.57, 1.67, 1.4, 1.64, 1.69, 1.58, 1.76, 1.69, 1.58, 1.72, 1.43, 1.7, 1.34, 1.69, 1.64, 1.6, 1.68, 1.5, 1.69, 1.5, 1.76, 1.47, 1.7, 1.63, 1.49, 1.48, 1.15, 1.59, 1.65, 1.6, 1.46, 1.43, 1.52, 1.55, 1.63, 1.41, 1.66, 1.62, 1.66, 1.66, 1.68, 1.63, 1.66, 1.59, 1.34, 1.67, 1.68, 1.46, 1.66, 1.77, 1.71, 1.71, 1.6, 1.47, 1.71, 1.75, 1.6, 1.58, 1.35, 1.72, 1.77, 1.68, 1.64, 1.71, 1.59, 1.63, 1.74, 1.39, 1.59, 1.71, 1.72, 1.25, 1.65, 1.7, 1.67, 1.71, 1.67, 1.49, 1.69, 1.36, 1.53, 1.73, 1.57, 1.58, 1.7, 1.61, 1.61, 1.7, 1.62, 1.69];

function extremeValues(crop) {
    const cropValues = values.filter((value, ix) => crops[ix] === crop)
    return {min: Math.min(...cropValues), max: Math.max(...cropValues)}
}

console.log(extremeValues(18157))

the "three-dot" notation is needed to transform an array into a list of argument for the variable-argument-count Math.min and Math.max functions.

An alternative to "three-dot" is to use the lodash library:

const _ = require("lodash")

var crops = [18002, 18154, 18154, 18155, 18155, 18155, 18156, 18156, 18156, 18156, 18157, 18157, 18157, 18157, 18157, 18158, 18158, 18158, 18158, 18158, 18158, 18159, 18159, 18159, 18159, 18159, 18159, 18159, 18160, 18160, 18160, 18160, 18160, 18160, 18160, 18160, 18160, 18161, 18161, 18161, 18161, 18161, 18161, 18161, 18161, 18161, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18162, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18163, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18164, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18165, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18166, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18167, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18168, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18169, 18170, 18170, 18170, 18170, 18170, 18170, 18170, 18170, 18170, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18171, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18172, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18173, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18174, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18175, 18176, 18176, 18176, 18176, 18176];
var values = [1.69, 1.65, 1.75, 1.7, 1.7, 1.78, 1.69, 1.62, 1.75, 1.74, 1.7, 1.72, 1.68, 1.77, 1.7, 1.62, 1.74, 1.69, 1.82, 1.68, 1.64, 1.66, 1.74, 1.57, 1.7, 1.7, 1.6, 1.66, 1.72, 1.47, 1.52, 1.7, 1.63, 1.67, 1.69, 1.7, 1.51, 1.49, 1.58, 1.63, 1.66, 1.68, 1.39, 1.71, 1.61, 1.62, 1.41, 1.52, 1.46, 1.41, 1.61, 1.65, 1.36, 1.59, 1.65, 1.64, 1.72, 1.52, 1.35, 1.49, 1.65, 1.32, 1.37, 1.69, 1.62, 1.63, 1.7, 1.72, 1.7, 1.3, 1.47, 1.56, 1.5, 1.67, 1.41, 1.73, 1.71, 1.67, 1.58, 1.73, 1.56, 1.66, 1.73, 1.57, 1.69, 1.58, 1.73, 1.47, 1.7, 1.8, 1.61, 1.77, 1.79, 1.63, 1.56, 1.58, 1.59, 1.84, 1.64, 1.77, 1.63, 1.7, 1.76, 1.73, 1.83, 1.63, 1.44, 1.32, 1.74, 1.46, 1.57, 1.67, 1.4, 1.64, 1.69, 1.58, 1.76, 1.69, 1.58, 1.72, 1.43, 1.7, 1.34, 1.69, 1.64, 1.6, 1.68, 1.5, 1.69, 1.5, 1.76, 1.47, 1.7, 1.63, 1.49, 1.48, 1.15, 1.59, 1.65, 1.6, 1.46, 1.43, 1.52, 1.55, 1.63, 1.41, 1.66, 1.62, 1.66, 1.66, 1.68, 1.63, 1.66, 1.59, 1.34, 1.67, 1.68, 1.46, 1.66, 1.77, 1.71, 1.71, 1.6, 1.47, 1.71, 1.75, 1.6, 1.58, 1.35, 1.72, 1.77, 1.68, 1.64, 1.71, 1.59, 1.63, 1.74, 1.39, 1.59, 1.71, 1.72, 1.25, 1.65, 1.7, 1.67, 1.71, 1.67, 1.49, 1.69, 1.36, 1.53, 1.73, 1.57, 1.58, 1.7, 1.61, 1.61, 1.7, 1.62, 1.69];

function extremeValues(crop) {
    const cropValues = values.filter((value, ix) => crops[ix] === crop)
    return {min: _.min(cropValues), max: _.max(cropValues)}
}

Of course, you need to incorporate the lodash library in order to have the latter option working.

Hope it helps - Carlos

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.