2

I have this object I want to sort and filter by retaining only the 2 highest values by object.

obj={ A :[{
      asset: 9,
      biodiversity: 4,
      infrastructure: 15,
      deflation: 11,
      energy: 9
    }],
  B:[{
      asset: 12,
      biodiversity: 10,
      infrastructure: 9,
      deflation: 7,
      energy: 15
    }],
  C:[{
      asset: 2,
      biodiversity: 12,
      infrastructure: 6,
      deflation: 6,
      energy: 8
    }]}

I would like to sort the objects by their values and filter out the 2 highest e.g:

{A :[{
      infrastructure: 15,
      deflation: 11
    }],
  B:[{
      energy: 15,
      asset: 12
    }],
  C:[{
      biodiversity: 12,
      energy: 8
    }]}

I have tried this for sorting:

Object.keys(obj).forEach((a) => _.sortBy(obj[a][0])))

But that is wrong obviously. I am using lodash but will accept vanilla javascript solution as well.

3
  • Please read the usage description of the json tag, and review your use of the word "json". This question has nothing to do with JSON. Commented Oct 4, 2020 at 20:03
  • well this is a valid (RFC 8259) so I don't know what you are talking about Commented Oct 4, 2020 at 20:17
  • Did you read the description of the json tag, and especially what is in CAPS? Anyway, I updated your question accordinly. Commented Oct 4, 2020 at 20:19

2 Answers 2

2

You could get the entries of the inner objects and sort by value descending, get the top two key/value pairs and build a new object from it.

const
    data = { A: [{ asset: 9, biodiversity: 4, infrastructure: 15, deflation: 11, energy: 9 }], B: [{ asset: 12, biodiversity: 10, infrastructure: 9, deflation: 7, nergy: 15 }], C: [{ asset: 2, biodiversity: 12, infrastructure: 6, deflation: 6, energy: 8 }]},
    result = Object.fromEntries(Object
        .entries(data)
        .map(([k, a]) => [k, a.map(o => Object.fromEntries(Object
            .entries(o)
            .sort((a, b) => b[1] - a[1])
            .slice(0, 2)
        ))])
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

Comments

0

(Edit/Note: This is based on the code you originally posted. I'm glad to see you updated your question and got rid of the wrapping array.)

Here's a relatively functional approach.

The secondLargestValue function finds the threshold value within each object. The copyWithoutValsBelowThreshold function gives us a modified copy of the object.

We loop though the entries in the top-level object and apply these two functions. See comments in the code for further clarification.

let json = getArray(); // Identifies the original array

// Defines `secondLargestVal` function
const secondLargestVal = someObj =>

  // Gets second item of array after sorting numerically in descending order
  Object.values(someObj).sort((a, b) => b - a)[1];

// Defines `copyWithoutValsBelowThreshold` function
const copyWithoutValsBelowThreshold = ( (someObj, threshold) => {

  // This function doesn't mutate the original value
  clone = Object.assign({}, someObj); // Copies obj
  for(let prop in clone){

    // Loops through properties, deleting non-qualifying ones
    if(clone[prop] < threshold){
      delete clone[prop];
    }
  }
  return clone;
});


// Defines our main function
const mutateJson = () => {
  let entries = Object.entries(json[0]);

  entries = entries.map(entry => {
    // `entry[0]` is the property name (eg: 'A') -- we don't actually use this
    // `entry[1]` is the value (in this case, an array containing a single object)
    let obj = entry[1][0]; // Identifies the actual object
    const threshold = secondLargestVal(obj); // Identifies minimum value
    
    // Updates the entry, deleting properties whose values are too low
    entry[1][0] = copyWithoutValsBelowThreshold(obj, threshold);
    return entry;
  });

  json[0] = Object.fromEntries(entries); // Replaces the top-level object
}


// Calls the main function
mutateJson();
console.log(json);


// Provides the original array
function getArray(){
  return [{ A :[{
      asset: 9,
      biodiversity: 4,
      infrastructure: 15,
      deflation: 11,
      energy: 9
    }],
  B:[{
      asset: 12,
      biodiversity: 10,
      infrastructure: 9,
      deflation: 7,
      energy: 15
    }],
  C:[{
      asset: 2,
      biodiversity: 12,
      infrastructure: 6,
      deflation: 6,
      energy: 8
    }]}]
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.