Home > Enterprise >  Filter elements of an array of objects comparing by various properties
Filter elements of an array of objects comparing by various properties

Time:06-17

I have a Javascript function that removes the elements of an array of objects that have the same property. What I am trying to do is create a generic method that can filter by several properties, and if there are two equal objects, filter by the property that has the highest value (test3)

This is the function I currently have, what I'm trying to do is make the function as generic as possible. What I want is for the keyConditional variable to be optional, but in this case, if I don't pass that variable to it, the function doesn't return anything. How can I solve this so that it is not mandatory to pass the keyConditional? How can I make this function as generic as possible to filter any object by any key (one or more)?

 let dataObj = [
  {
    "test1": "model",
    "test2": "dataFile",
    "test3": "2022-06-15"
  },
  {
    "test1": "model",
    "test2": "dataFile",
    "test3": "2022-06-10"
  },
  {
    "test1": "data",
    "test2": "mode",
    "test3": "2022-06-08"
  }
]

function filterObjectsSomeKeys(dataObj, keysFilter, keyConditional) {

  const result = Object.values(dataObj.reduce((prevValue, currValue) => {
    const key = keysFilter.map(key => 
      currValue[key]
    ).join('|');

    if (keyConditional) {
      if(!prevValue[key] || prevValue[key].keyConditional < currValue.keyConditional) {
        prevValue[key] = currValue;
      }
    }
    return prevValue;    
  }, {}));

  return result;
}

console.log(filterObjectsSomeKeys(dataObj,['test1','test2'],'test3'))

CodePudding user response:

You could iterate the array directly without getting values from the object, which ist an additional superfluous step.

For using more than one key, take an array of keys and build a combined hash value and take only the object if the hash does not exist or the wanted key of the actual object is greater than the latest value of the same key.

const
    filter = (array, group, keyConditional) => Object.values(data.reduce((r, o) => {
        const key = group.map(k => o[k]).join('|');
        if (!r[key] || keyConditional && o[keyConditional] > r[key][keyConditional]) r[key] = o;
        return r;
    }, {})),
    data = [
        { test1: "model", test2: "dataFile", test3: "2022-06-15" },
        { test1: "model", test2: "dataFile", test3: "2022-06-17" },
        { test1: "data", test2: "mode", test3: "2022-06-08" },
        { test1: "data", test2: "raw", test3: "2022-01-01" }
    ];

console.log(filter(data, ['test1', 'test2']));
console.log(filter(data, ['test1', 'test2'], 'test3'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

CodePudding user response:

Unless I'm misunderstanding, this should work.

const result = dataObj.reduce((mostRecentObject, currentObject) => {
  const mostRecentObjectTime = Date(mostRecentObject['test3'].getTime()
  const currentObjectTime = Date(currentObject['test3'].getTime()

  const currentObjectIsMoreRecent = currentObjectTime > mostRecentObjectTime

  return currenctObjectIsMoreRecent ? currentObject : mostRecentObject
}, dataObj[0])

This should return the object within the dataObj array where the value of test3 is the most recent.

  • Related