4

I am breaking my head trying to figure how to achieve what I need. My initial array of objects is 70k objects with 15 attributes each. Through filtering and mapping, I have gotten the data set down to what I think are the relevant parts. I need to return a new array of objects based on each of the 4 properties of each object, with their being duplicate id's and different levels for each code. My filtered data looks like so.

const arr = [{id: "12345", level: "1", current: "Y", code: "1"}, 
             {id: "12345", level: "0", current: "N", code: "1"},
             {id: "54321", level: "1", current: "N", code: "201"},
             {id: "54321", level: "2", current: "Y", code: "201"}, 
             {id: "54321", level: "3", current: "N", code: "201"},
             {id: "54321", level: "0", current: "Y", code: "401"},
             {id: "54321", level: "1", current: "N", code: "401"},
             {id: "54321", level: "3", current: "N", code: "201"},
             {id: "54321", level: "0", current: "N", code: "301"},
             {id: "121212", level: "0", current: "N", code: "3"},
             {id: "121212", level: "1", current: "N", code: "3"}]

What I need to achieve is for each id for any current of Y for each code, I need to find the max level for that code. So for the example above the resulting output would be an array of objects like so:

const result = [{id: "12345", max: "1", code: "1"}, 
                {id: "54321", max: "3", code: "201"},
                {id: "54321", max: "1", code: "401"}]

I'm not even sure if what I want is possible, or if I'm thinking about it the wrong way. I have been racking my brain all morning trying to figure out a solution.

3
  • if " for any current of Y" then shouldn't ihe max values be 1,0,2 instead of 1,3,1 ? Commented Aug 9, 2018 at 17:23
  • @mickl I may have worded it wrong, but for any code that has a 'Y' for each id I need to find the max of that code for the id. I need the max level for each code that has a 'Y' Commented Aug 9, 2018 at 17:45
  • Thanks, modified my answer, now it returns what you need Commented Aug 9, 2018 at 17:52

4 Answers 4

2

You can use .filter() and .map() to get initial values based on Y and then .reduce() to get max values:

const arr = [{id: "12345", level: "1", current: "Y", code: "1"}, 
             {id: "12345", level: "0", current: "N", code: "1"},
             {id: "54321", level: "1", current: "N", code: "201"},
             {id: "54321", level: "2", current: "Y", code: "201"}, 
             {id: "54321", level: "3", current: "N", code: "201"},
             {id: "54321", level: "0", current: "Y", code: "401"},
             {id: "54321", level: "1", current: "N", code: "401"},
             {id: "54321", level: "3", current: "N", code: "201"},
             {id: "54321", level: "0", current: "N", code: "301"},
             {id: "121212", level: "0", current: "N", code: "3"},
             {id: "121212", level: "1", current: "N", code: "3"}]

let initialValues = arr.filter(x => x.current === "Y")
		       .map(x => ({ id: x.id, max: x.level, code: x.code }));

let result = arr.reduce((result,current) => {
	var value = result.find(x => x.id === current.id && x.code === current.code);
	if(!value) return result;
	if(value.max < current.level) {
		value.max = current.level;
	}
	return result;
}, initialValues);

console.log(result);

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

1 Comment

Works like a charm. Thank you!
2

You could reduce to a Map and take its values

const arr = [{id: "12345", level: "1", current: "Y", code: "1"},
    {id: "12345", level: "0", current: "N", code: "1"},
    {id: "54321", level: "1", current: "N", code: "201"},
    {id: "54321", level: "2", current: "Y", code: "201"},
    {id: "54321", level: "3", current: "N", code: "201"},
    {id: "54321", level: "0", current: "Y", code: "401"},
    {id: "54321", level: "1", current: "N", code: "401"},
    {id: "54321", level: "3", current: "N", code: "201"},
    {id: "54321", level: "0", current: "N", code: "301"},
    {id: "121212", level: "0", current: "N", code: "3"},
    {id: "121212", level: "1", current: "N", code: "3"}];
    
    
const res = arr.reduce((a, b) =>
  b.current === 'Y' ?
  a.set(b.id + b.code, (a.get(b.id + b.code) || {
    level: Number.MIN_SAFE_INTEGER
  }).level < b.level ? b : a.get(b.id + b.code)) :
  a, new Map);
console.log([...res.values()]);

1 Comment

OP is expecting different result
2

You can simply achieve a Array.reduce() and Object destructuring. construct a map with each key a combination of id and code. Simply use Object.values() on the map to get the desired result :

const arr = [{id: "12345", level: "1", current: "Y", code: "1"}, {id: "12345", level: "0", current: "N", code: "1"}, {id: "54321", level: "1", current: "N", code: "201"}, {id: "54321", level: "2", current: "Y", code: "201"}, {id: "54321", level: "3", current: "N", code: "201"}, {id: "54321", level: "0", current: "Y", code: "401"}, {id: "54321", level: "1", current: "N", code: "401"}, {id: "54321", level: "3", current: "N", code: "201"}, {id: "54321", level: "0", current: "N", code: "301"}, {id: "121212", level: "0", current: "N", code: "3"}, {id: "121212", level: "1", current: "N", code: "3"}];
             
const result = Object.values(arr.reduce((a,{level,current, ...props})=>{
    a[props.id+"_"+props.code] = a[props.id+"_"+props.code] || props;
    a[props.id+"_"+props.code].max = Math.max((a[props.id+"_"+props.code].max || 0), level);
  return a;
},{}));
console.log(result);

Comments

0
const resultObject = (arr, filter) => arr.reduce((sum, element) => {
  const currentInSum = sum[element.id];
  const filterSatisfied = element.current === filter;
  const isHighestLevel = !currentInSum  || currentInSum.level < element.level;
  if(filterSatisfied && isHighestLevel){
     sum[element.id] = element;
  }
  return sum;
}, {});
const result = Object.values(resultObject(arr, "Y"));

Basically you want to use an object so that you can check whether the element is already added, and if the current level is higher than the one already added, then replace it, if this is the first occurence then just add it to the object.

Lastly, just get all the values from the object to convert it to an array, you don't care about the keys which is the object's id.

This algorithm takes O(n*2) time to execute, since you have to run through arr once, and then you have to convert all the values in the object into an array

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.