递归处理JSON数组以查找数组中所有对象的通用值

时间:2019-01-28 18:04:22

标签: javascript arrays node.js json recursion

在过去的几天里,我一直非常努力地递归处理此JSON结构,希望有人能为我提供帮助。

我有一个包含多个JSON对象的数组。每个对象代表一个问题,并具有一个或多个可能的答案。每个答案包含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数组中找到一个匹配元素。

总是会有比答案更少的数据点,因此我需要知道可以为每个数据点分配什么值,以便在potentialAnswer数组中为每个问题有一个有效的对象。如果没有这种可能的组合,则需要提醒我。

每个数据点最终只能有一个值,因此,无论它们分配的值如何,都不会与其他问题的答案相冲突。这将被视为一个总体目标答案。

一些其他信息:

  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;
}

1 个答案:

答案 0 :(得分:0)

在将我的头撞在墙上之后,我最终找到了我想要的解决方案。

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

SELECT * FROM aadhar LIMIT 1.500000000