Home > Net >  What is the proper way to match key and value from an array of objects and return a new object with
What is the proper way to match key and value from an array of objects and return a new object with

Time:09-07

I'm trying to make a function in javascript in order to match a key and an array of objects from an API. The matching is based on 2 parameters coming from an API. A key which is a string and an array of objects with keys and values. The output of this match should be a new array of objects with the values where that passed key is matching with the key of that array of objects passed as a parameter.

I prepared a sample of what I'm trying to achieve but is not working as I don't know how to do it properly and below it will be moe details about it

const criteriaJson = [{
    "age": {
      "min": "18",
      "max": "65"
    },
    "pain": {
      "min": "5"
    },
    "disease": {
      "valid": [
        "MDD",
        "PTSD"
      ],
      "invalid": [
        "None"
      ]
    },
    "medicines": "true",
    "bmi": {
      "min": "25",
      "max": "100"
    },
    "weight": "90",
    "gender": [
      "1",
      "2",
      "3"
    ],
    "pressure": "100",
    "smoker": "20",
    "zip": "^w s{1}w $"
  },
  {
    "age": {
      "min": "16",
      "max": "18"
    },
    "pain": {
      "max": "10"
    },
    "bmi": {
      "max": "85"
    },
    "disease": {
      "valid": [
        "none"
      ],
      "invalid": [
        "PTT",
        "ADT",
        "OLL"
      ]
    },
    "weight": "70",
    "gender": [
      "1"
    ],
    "pressure": "10"
  }
]

const question = {
  key: "medicines"
}



// *Matching and extracting the right criteria data for the provided question key
// *inside the criteria object
// *returns an object with the right criteria
// *doing it for every group set of rules
function questionCriteriaKeyMatch(criteriaJson, question) {
  criteriaJson.map((criteria) => {
    return Object.keys(criteria)
      .filter((key) => {
        return key === question.key;
      })
      .reduce((cur, key) => {
        return Object.assign(cur, {
          criteria: criteria[key],
        });
      }, {});
  });
}

console.log(questionCriteriaKeyMatch(criteriaJson, question));

To explain what data we are getting that criteriaJson This data is an array of objects which contains a set of rules divided into objects for the same item but referring to a different group.

object 1 is criteria 1 and object 2 is criteria 2 to make it simple in this specific case.

[{
    "age": {
      "min": "18",
      "max": "65"
    },
    "pain": {
      "min": "5"
    },
    "disease": {
      "valid": [
        "MDD",
        "PTSD"
      ],
      "invalid": [
        "None"
      ]
    },
    "medicines": "true",
    "bmi": {
      "min": "25",
      "max": "100"
    },
    "weight": "90",
    "gender": [
      "1",
      "2",
      "3"
    ],
    "pressure": "100",
    "smoker": "20",
    "zip": "^w s{1}w $"
  },
  {
    "age": {
      "min": "16",
      "max": "18"
    },
    "pain": {
      "max": "10"
    },
    "bmi": {
      "max": "85"
    },
    "disease": {
      "valid": [
        "none"
      ],
      "invalid": [
        "PTT",
        "ADT",
        "OLL"
      ]
    },
    "weight": "70",
    "gender": [
      "1"
    ],
    "pressure": "10"
  }
]

However, the cases for this data are 3 essentially

  1. the object is empty as no criteria exist in this case from API the match with the key which doesn't exist will output null
  2. the array has one object only so the match needs to be done on this only object and if the key does not match output null
  3. we have an array of more than one object in this case we need to match for every single object the key and if not match output is null.

Starting with the simple case when we receive an empty array of objects

const obj = [];
const key = 'someKey';

// Output as there is no matching
[null]

Example of the second case, when we have one object in the array

const obj = [{
  "age": {
      "min": "18",
      "max": "65"
    },
    "pain": {
      "min": "5"
    },
    "disease": {
      "valid": [
        "MDD",
        "PTSD"
      ],
      "invalid": [
        "None"
      ]
    },
}]

// Output matching key === age -> I'm open to suggestions how this output should be for // one obj only in the array

[{
  criteria: { min:"18", max:"65" }
}]

// key === pain

[{
 criteria: "5"
}]

// key === disease

[{
  criteria: {valid: ["MDD","PTSD"], invalid: ["None"] }
}]

// key === notExistingKey means the key we are passing to match doesn't have a match so // we output null in this case

[{ null }]

From the above example, we output the matching values with the key passed as a param, when no match then is null

The last case is the more complex probably when we have an array of objects of the criteria and this should work for an array length > 1.

Using same data as in the snippet showing what is the expected output


const criteriaJson = [{
    "age": {
      "min": "18",
      "max": "65"
    },
    "pain": {
      "min": "5"
    },
    "disease": {
      "valid": [
        "MDD",
        "PTSD"
      ],
      "invalid": [
        "None"
      ]
    },
    "medicines": "true",
    "bmi": {
      "min": "25",
      "max": "100"
    },
    "weight": "90",
    "gender": [
      "1",
      "2",
      "3"
    ],
    "pressure": "100",
    "smoker": "20",
    "zip": "^w s{1}w $"
  },
  {
    "age": {
      "min": "16",
      "max": "18"
    },
    "pain": {
      "max": "10"
    },
    "bmi": {
      "max": "85"
    },
    "disease": {
      "valid": [
        "none"
      ],
      "invalid": [
        "PTT",
        "ADT",
        "OLL"
      ]
    },
    "weight": "70",
    "gender": [
      "1"
    ],
    "pressure": "10"
  }
]

const key = 'medicines'

// the output should be a new array of objects as we need to compare each object to find // the key match and output every single value
// key === medicines

[
 {  criteria: 'true' }, -> we have a match in the first obj
 {  criteria: null   }, -> we have no match in the second obj 
]

// key === age

[
 {  criteria: { min: "18", max: "65" }},  -> we have a match in the first obj
 {  criteria: { min: "16", max: "18" }}}, -> we have a match in the second obj 
]

// For the rest of the keys should follow the same logic and with more objects, we have more 
// objects in the output we have 

I'm adding criteria as I need that in a second phase to be able to access that obj and extract the values for further use. As the keys are not the same always as are strings from API set in a client I need a way to facilitate access to the new object by assigning a hard-coded key. That is why when there is a match I just need the values and key like criteria, so I can access without an issue the values

I started with a reduce method as I thought maybe that was the way but in the end, I'm open to new solutions as cannot figure out how to achieve my goal.

The important note is that I cannot use for loops as I have strict rules of code style which cannot change.

If will be any comment with particular questions or request will try to explain better or update my question with more relevant info.

CodePudding user response:

Seems like you just want to map the array to a new array with just the values. If the key does not exist, you would just set the criteria value to null, otherwise you set the criteria to whatever the property's value is.

const criteriaJson = [{
    "age": {
      "min": "18",
      "max": "65"
    },
    "pain": {
      "min": "5"
    },
    "disease": {
      "valid": [
        "MDD",
        "PTSD"
      ],
      "invalid": [
        "None"
      ]
    },
    "medicines": "true",
    "bmi": {
      "min": "25",
      "max": "100"
    },
    "weight": "90",
    "gender": [
      "1",
      "2",
      "3"
    ],
    "pressure": "100",
    "smoker": "20",
    "zip": "^w s{1}w $"
  },
  {
    "age": {
      "min": "16",
      "max": "18"
    },
    "pain": {
      "max": "10"
    },
    "bmi": {
      "max": "85"
    },
    "disease": {
      "valid": [
        "none"
      ],
      "invalid": [
        "PTT",
        "ADT",
        "OLL"
      ]
    },
    "weight": "70",
    "gender": [
      "1"
    ],
    "pressure": "10"
  }
]

function getCriteria (key, data) {
  if (!data?.length) return [null]
  return data.map(item => ({ criteria: item[key] || null }));
}

console.log('age', getCriteria('age', criteriaJson));
console.log('medicines', getCriteria('medicines', criteriaJson));
console.log('pressure', getCriteria('pressure', criteriaJson));

  • Related