简单的Javascript循环创建多个分组 - 如何改进

时间:2018-04-30 02:26:25

标签: javascript

以下是我从localStorage获得的对象。

{RxField: "2", soapName: "", soapQuestion: "", soapAnswer: "Chest pain last 2 days", soapScore: "NA"}
{RxField: "2", soapName: "CBAM", soapQuestion: "Shortness of Breath", soapAnswer: "Yes", soapScore: ""}
{RxField: "2", soapName: "CBAM", soapQuestion: "Coughing more than 2 Weeks", soapAnswer: "Yes", soapScore: ""}
{RxField: "2", soapName: "ChestPainHPI", soapQuestion: "Location", soapAnswer: "Right Arm", soapScore: ""}
{RxField: "2", soapName: "ChestPainHPI", soapQuestion: "Quality", soapAnswer: "Pressure", soapScore: ""}
{RxField: "3", soapName: "", soapQuestion: "", soapAnswer: "Insignification", soapScore: "NA"}
{RxField: "3", soapName: "CxHistory", soapQuestion: "Past problems with medication", soapAnswer: "Acne", soapScore: ""}
{RxField: "3", soapName: "CxHistory", soapQuestion: "Menses onset age", soapAnswer: "14", soapScore: ""}
{RxField: "3", soapName: "CxHistory", soapQuestion: "Gravida", soapAnswer: "Elderly Primigravida", soapScore: ""}

我想循环使用它来打印它:

**RX FIELD - 2**
: Chest pain last 2 days
**CBAM**
Shortness of Breath: Yes
Coughing more than 2 Weeks: Yes
**ChestPainHPI**
Location: Right Arm
Quality: Pressure
**RX FIELD - 3**
: Insignificant
**ContraceptionHistory**
Past problems with medication: Acne
Menses onset age: 14
Gravida: Elderly Primigravida

虽然我设法做到了这一点,但我并不喜欢它。有可能做得更好吗?

function GetAnswers(){
  $('#rez').empty();//clear div of old values
  var trm = localStorage.getItem('erxval');
  trm2 = JSON.parse(trm);
  //console.log(groupsz);
  //global function for making groups in array
  Array.prototype.groupBy = function(prop) {
    return this.reduce(function(groups, item) {
      var val = item[prop];
      groups[val] = groups[val] || [];
      groups[val].push(item);
      return groups;
    }, {});
  };//global function end

  var rxfieldgroup = trm2.groupBy("RxField");//group by rxfield
  //console.log(rxfieldgroup);
  var keyz = Object.keys(rxfieldgroup);//get keys of the array groups made by the above function
  coL = Object.keys(rxfieldgroup).length;// count number of keys for using in for loop
  var str = "";
  for(i=0;i<coL;i++){// this loop creates all the lables for  RX fiekds
    str = `<div><label id="${keyz[i]}">${keyz[i]}</label><section id="sec_${keyz[i]}"></section></div>`;
    $('#rez').append(str);
    var moreArs = rxfieldgroup[keyz[i]];
    var sG = moreArs.groupBy("soapName");//create sub group by of seperated templates
    console.log(sG);
    var soapKey = Object.keys(sG);//get keys of of the sub group arrays
    for(j=0;j<soapKey.length;j++){//this function loops through each section of template
      if(soapKey[j]){
        ptr = `<h4><label>${soapKey[j]}</label><li id="qa_${soapKey[j]}"></li></h4>`;//and displays Soap Template Names 
      }else{
        ptr = `<h4><label>${soapKey[j]}</label><li id="qa_${keyz[i]}"></li></h4>`;
      }
      $("#sec_"+keyz[i]).append(ptr);
      levelthree = sG[soapKey[j]];
      for(k=0;k<levelthree.length;k++){//this loops through to insert question and answer 
        qtr = `<p>${levelthree[k].soapQuestion}:  <span>${levelthree[k].soapAnswer}</span></p>`;
        console.log(soapKey[j]);
        if(soapKey[j]){
          $("#qa_"+soapKey[j]).append(qtr);
        }else{
          $("#qa_"+keyz[i]).append(qtr);
        }
      }
    }   
  }
}

1 个答案:

答案 0 :(得分:0)

您可以使用递归函数一次性执行此操作:

const data = [
  {RxField: "2", soapName: "", soapQuestion: "", soapAnswer: "Chest pain last 2 days", soapScore: "NA"},
  {RxField: "2", soapName: "CBAM", soapQuestion: "Shortness of Breath", soapAnswer: "Yes", soapScore: ""},
  {RxField: "2", soapName: "CBAM", soapQuestion: "Coughing more than 2 Weeks", soapAnswer: "Yes", soapScore: ""},
  {RxField: "2", soapName: "ChestPainHPI", soapQuestion: "Location", soapAnswer: "Right Arm", soapScore: ""},
  {RxField: "2", soapName: "ChestPainHPI", soapQuestion: "Quality", soapAnswer: "Pressure", soapScore: ""},
  {RxField: "3", soapName: "", soapQuestion: "", soapAnswer: "Insignification", soapScore: "NA"},
  {RxField: "3", soapName: "CxHistory", soapQuestion: "Past problems with medication", soapAnswer: "Acne", soapScore: ""},
  {RxField: "3", soapName: "CxHistory", soapQuestion: "Menses onset age", soapAnswer: "14", soapScore: ""},
  {RxField: "3", soapName: "CxHistory", soapQuestion: "Gravida", soapAnswer: "Elderly Primigravida", soapScore: ""},
  {RxField: "5", soapName: "CxHistory", soapQuestion: "Gravida", soapAnswer: "Elderly Primigravida", soapScore: ""}
];

const dataToString = data => {
  const closeTags = ["</ul></div>","</div>",""];//at what level we need to close
  const closeAtLevel = level =>//if at main level, close </div> if at sub close li and divs
    closeTags.slice(level).reduce((all,item)=>all+item);
  const openMain = item => `
    <div>
      <h1>RX FIELD - ${item.RxField}</h1>
    `;
  const openSub = item => `
    <div>
      <h2>${item.soapName}</h2>
      <ul>
        <li>${item.soapQuestion}:${item.soapAnswer}</li>
    `;
  const recur = (result,nextExpected,rest,level) => {
    if(rest.length===0){//no more items left
      return result+closeAtLevel(level);//return result plus closing tags
    }
    if(nextExpected[0]!==rest[0].RxField){//RxField changed, open main item
      return recur(//call itself recursively
        result + closeAtLevel(level) + openMain(rest[0]),//close tags and open main tags
        [rest[0].RxField,{}],//next expected values for RxField and soapName
        rest.slice(1),//processed this item, take it off the rest items
        1//indicate we opened a main level tag
      );
    }
    if(nextExpected[1]!==rest[0].soapName){//soapName changed
      const close = (level===0)?closeTags[0]:"";//depending on level we were determine close tag
      return recur(//call itself recursively
        result + close + openSub(rest[0]),//optional close tags plus opening a sub list
        [nextExpected[0],rest[0].soapName],//next expected RxField and soapName
        rest.slice(1),//rest of the items minus the currently processed one
        0//we opened main and sub level <div><div><ul> so need to close them at some point
      );
    }
    return recur(//call itself recursively
      result + `
            <li>${rest[0].soapQuestion}:${rest[0].soapAnswer}</li>
      `,//nothing changed, just add the item to the list
      nextExpected,//nothing changed next expected RxField and soapName stay the same
      rest.slice(1),//take off current processed item
      0//still need to close <div><div><ul>
    );
  }
  return recur ([],[{},{}],data,-1);
}

document.getElementById("content").innerHTML = dataToString(data);
<div id="content"></div>