javascript - 递归处理 JSON 数组以查找数组中所有对象的共同值

标签 javascript arrays node.js json recursion

过去几天我一直在努力递归处理这个 JSON 结构,希望有人能帮助我。

我有一个包含多个 JSON 对象的数组。每个对象代表一个问题并有 1 个或多个可能的答案。每个答案包含 1 个或多个可能的条件,这些条件又包含 1 个数据点和 1 个 requiredValue。

JSON 对象

[
  {
    "originalQ": "Have you been to hospital?",
    "originalA": "No",
    "potentialAnswers": [
      {
        "conditions": [
          {
            "datapoint": "Hospitalization",
            "assoicatedValue": "more than 2 years ago "
          }
        ]
      },
      {
        "conditions": [
          {
            "datapoint": "Hospitalization",
            "assoicatedValue": "never"
          }
        ]
      }
    ]
  },
  {
    "originalQ": "Has a medical professional diagnosed you?",
    "originalA": "No",
    "potentialAnswers": [
      {
        "conditions": [
          {
            "datapoint": "OtherDiagnosis",
            "assoicatedValue": "has never"
          },
          {
            "datapoint": "Hospitalization",
            "assoicatedValue": "never"
          }
        ]
      }
    ]
  },
  {
    "originalQ": "Are you taking medication?",
    "originalA": "Yes",
    "potentialAnswers": [
      {
        "conditions": [
          {
            "datapoint": "Medications",
            "assoicatedValue": "1-3"
          }
        ]
      },
      {
        "conditions": [
          {
            "datapoint": "Medications",
            "assoicatedValue": "4 or more"
          }
        ]
      }
    ]
  },
  {
    "originalQ": "How many different medications do you take?",
    "originalA": "4 or more",
    "potentialAnswers": [
      {
        "conditions": [
          {
            "datapoint": "Medications",
            "assoicatedValue": "4 or more"
          }
        ]
      }
    ]
  }
]

我需要获取一个包含 datapoint:assoicatedValue 对的 JSON 对象,该对象使我们能够在每个问题对象的每个问题潜在答案数组中找到一个匹配元素。

数据点总是少于答案,因此我需要知道可以为每个数据点分配什么值,以便在每个问题的 PotentialAnswer 数组中拥有 1 个有效对象。如果不存在这种可能的组合,我需要对此发出警报。

最终,每个数据点只能有一个值,因此分配给它们的任何值都不能与其他问题的答案相冲突。这将被视为整体对象答案。

一些附加信息:

  1. 每个都是动态生成的,即数据点名称可以在运行之间更改(但同一运行的对象之间保持一致),问题对象的数量会发生变化。
  2. 在某些情况下,无法找到数据点值,在这种情况下,函数应返回该信息。

下面的结果至少与每个问题中的一个潜在答案相匹配。

所需结果

{
  "Hospitalization": "never ",
  "OtherDiagnosis": "has never",
  "Medications": "4 or more"
}

我尝试了多种方法,但总是遇到无法解决的问题。下面的代码是我得到的最接近的代码。它在大多数情况下都有效,但如果在最后一个问题对象中遇到问题,似乎会​​出现问题。

代码尝试

let allQuestionData = require('./datafile.1.json');

findCorrectAnswerCombination(allQuestionData);

function findCorrectAnswerCombination(allQuestionData) {
    console.log(ProcessNextQuestion(allQuestionData));
}

//This function will run all of the next questions
function ProcessNextQuestion(allQuestions, startingIndex = 0, dpObj = {}, questionNum = 1) {
    try{
        //create deep copy of Obj
        let copyDpObj = JSON.parse(JSON.stringify(dpObj))

        //Loop through all of the remaining questions
        for (let i = startingIndex; i < allQuestions.length; i++) {
            let question = allQuestions[i];

            for (let answerNum = 0; answerNum < question.potentialAnswers.length; answerNum++) {
                let answer = question.potentialAnswers[answerNum];

                //Determine if the current potential answer fits with the values already in the dpObj
                if (doesAnswerFitInCurrentDPObject(answer, copyDpObj)) {

                    //Add the new datapoints to the doObj if there are any new dps
                    let tempDPObj = addValuesToDpObj(answer, dpObj);

                    //if this is the final question then we have a valid path
                    if (questionNum === allQuestions.length) {
                        return tempDPObj;
                    } else {
                        //recurively run on remaining questions
                        return ProcessNextQuestion(allQuestions, i + 1, tempDPObj, questionNum + 1);
                    }
                }
            }    
        }
        return 'No matching values found'

    }catch(err){
        throw new Error(err)
    }

}

function doesAnswerFitInCurrentDPObject(answer, dpObj) {

    for (const condition of answer.conditions) {
        if (dpObj.hasOwnProperty(condition.datapoint) && dpObj[condition.datapoint] !== condition.assoicatedValue) {
            return false;
        }
    }
    return true;
}

function addValuesToDpObj(answer, currentDpObj) {
    let copyObj = JSON.parse(JSON.stringify(currentDpObj));

    for (const condition of answer.conditions) {
        copyObj[condition.datapoint] = condition.assoicatedValue;
    }

    return copyObj;
}

最佳答案

经过多次用头撞墙之后,我最终找到了我正在寻找的解决方案。

我没有正确处理值的返回。我需要在调用递归后检查是否找到正确的值。如果是的话,我需要另一个 return 语句来结束该循环。在这种情况下,我的循环将一直存在到开头。本来无论是否找到该值都会返回。

//This function will run all of the next questions
function ProcessNextQuestion(allQuestions, startingIndex = 0, dpObj = {}, questionNum = 1) {
    try {
        //create deep copy of Obj
        let copyDpObj = JSON.parse(JSON.stringify(dpObj))

        //Loop through all of the remaining questions
        for (let i = startingIndex; i < allQuestions.length; i++) {
            let question = allQuestions[i];

            for (let answerNum = 0; answerNum < question.potentialAnswers.length; answerNum++) {
                let answer = question.potentialAnswers[answerNum];

                //Determine if the current potential answer fits with the values already in the dpObj
                if (doesAnswerFitInCurrentDPObject(answer, copyDpObj)) {

                    //Add the new datapoints to the doObj if there are any new dps
                    let tempDPObj = addValuesToDpObj(answer, dpObj);

                    //if this is the final question then we have a valid path
                    if (questionNum === allQuestions.length) {
                        return tempDPObj;
                    } else {

              //******************
              // This is what I needed to add
              //******************
                        //recurively run on remaining questions
                        let processingResultFound = ProcessNextQuestion(allQuestions, i + 1, tempDPObj, questionNum + 1);
                        if (processingResultFound !== 'No matching values found') {
                            return processingResultFound;
                        }
              //******************

                    }
                }
            }
        }
        return 'No matching values found'

    } catch (err) {
        throw new Error(err)
    }
}

关于javascript - 递归处理 JSON 数组以查找数组中所有对象的共同值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54407825/

相关文章:

javascript - 使用addEventListener时事件参数是如何传递的?

javascript - 无法在mvc中的angular js bootstrap中使用超时

javascript - 在 Azure 移动服务上使用服务器端脚本修改响应

javascript - "undefined"不是 list 数组上设置监听器的函数

c++ - 指向数组的指针更改数组元素的值

javascript - 在 for 循环中将对象添加到 'Json Array of Objects'

node.js - 使用 Hapi、MongoDb、NodeJS 和 AngularJS 创建实时项目

javascript - Promise then 不是 Node Promise 的函数错误

javascript - 通过ajax发送带有字母数字索引名称的数组

javascript - Iron Router 将参数添加到字符串以及添加查询