代码之家  ›  专栏  ›  技术社区  ›  justDan

递归地循环对象的对象

  •  1
  • justDan  · 技术社区  · 4 年前

    我正在尝试编写一个递归函数来遍历一个对象并根据一个ID返回项。我可以让它的第一部分正常工作,但是我很难以递归的方式获得这个函数,并且可能需要一组新的眼睛。代码如下。当你运行代码片段时,你得到了一个包含6个项目的数组,对于第一次迭代来说,这正是我想要的,但是我如何用适当的参数调用我的函数来获得嵌套的项呢?我的最终目标是将所有以“Cstm”开头的对象(嵌套的对象)添加到tablesAndValues数组中。我试着在这之后建立我的代码模型: Get all key values from multi level nested array JavaScript

    JSIDLE地址: https://jsfiddle.net/xov49jLs/

    const response = {
      "data": {
        "Cstm_PF_ADG_URT_Disposition": {
          "child_welfare_placement_value": ""
        },
        "Cstm_PF_ADG_URT_Demographics": {
          "school_grade": "family setting",
          "school_grade_code": ""
        },
        "Cstm_Precert_Medical_Current_Meds": [
          {
            "med_name": "med1",
            "dosage": "10mg",
            "frequency": "daily"
          },
          {
            "med_name": "med2",
            "dosage": "20mg",
            "frequency": "daily"
          }
        ],
        "Cstm_PF_ADG_URT_Substance_Use": {
          "dimension1_comment": "dimension 1 - tab1",
          "Textbox1": "text - tab1"
        },
        "Cstm_PF_ADG_Discharge_Note": {
          "prior_auth_no_comm": "auth no - tab2"
        },
        "Cstm_PF_ADG_URT_Clinical_Plan": {
          "cca_cs_dhs_details": "details - tab2"
        },
        "container": {
          "Cstm_PF_Name": {
            "first_name": "same text for textbox - footer",
            "last_name": "second textbox - footer"
          },
          "Cstm_PF_ADG_URT_Demographics": {
            "new_field": "mapped demo - footer"
          },
          "grid2": [
            {
              "Cstm_PF_ADG_COMP_Diagnosis": {
                "diagnosis_label": "knee",
                "diagnosis_group_code": "leg"
              }
            },
            {
              "Cstm_PF_ADG_COMP_Diagnosis": {
                "diagnosis_label": "ankle",
                "diagnosis_group_code": "leg"
              }
            }
          ]
        },
        "submit": true
      }
    };
    
    function getNamesAndValues(data, id) {
      const tablesAndValues = [],
            res = data;
     
      Object.entries(res).map(([key, value]) => {
        const newKey = key.split('_')[0].toLowerCase();
        
        // console.log(newKey) // -> 'cstm'
        
        if (newKey === id) {
          tablesAndValues.push({
            table: key,
            values: value
          });
        } else {
          // I can log value and key and see what I want to push 
          // to the tablesAndValues array, but I can't seem to get 
          // how to push the nested items.
          
          // console.log(value);
          // console.log(key);
          
          // getNamesAndValues(value, key)
        }
      });
      
      return tablesAndValues;
    }
    
    console.log(getNamesAndValues(response.data, 'cstm'));
    2 回复  |  直到 4 年前
        1
  •  1
  •   traktor    4 年前

    .map .forEach 由于未使用返回值:

    const response = {
      "data": {
        "Cstm_PF_ADG_URT_Disposition": {
          "child_welfare_placement_value": ""
        },
        "Cstm_PF_ADG_URT_Demographics": {
          "school_grade": "family setting",
          "school_grade_code": ""
        },
        "Cstm_Precert_Medical_Current_Meds": [
          {
            "med_name": "med1",
            "dosage": "10mg",
            "frequency": "daily"
          },
          {
            "med_name": "med2",
            "dosage": "20mg",
            "frequency": "daily"
          }
        ],
        "Cstm_PF_ADG_URT_Substance_Use": {
          "dimension1_comment": "dimension 1 - tab1",
          "Textbox1": "text - tab1"
        },
        "Cstm_PF_ADG_Discharge_Note": {
          "prior_auth_no_comm": "auth no - tab2"
        },
        "Cstm_PF_ADG_URT_Clinical_Plan": {
          "cca_cs_dhs_details": "details - tab2"
        },
        "container": {
          "Cstm_PF_Name": {
            "first_name": "same text for textbox - footer",
            "last_name": "second textbox - footer"
          },
          "Cstm_PF_ADG_URT_Demographics": {
            "new_field": "mapped demo - footer"
          },
          "grid2": [
            {
              "Cstm_PF_ADG_COMP_Diagnosis": {
                "diagnosis_label": "knee",
                "diagnosis_group_code": "leg"
              }
            },
            {
              "Cstm_PF_ADG_COMP_Diagnosis": {
                "diagnosis_label": "ankle",
                "diagnosis_group_code": "leg"
              }
            }
          ]
        },
        "submit": true
      }
    };
    
    function getNamesAndValues(data, id, tablesAndValues = []) {
      const res = data;
     
      Object.entries(res).forEach(([key, value]) => {
        const newKey = key.split('_')[0].toLowerCase();
        if (newKey === id) {
          tablesAndValues.push({
            table: key,
            values: value
          });
        } else {
            getNamesAndValues( value, id, tablesAndValues);    }
      });
        return tablesAndValues;
    }
    
    console.log(getNamesAndValues(response.data, 'cstm'));
        2
  •  1
  •   David Nithael Torres Lima    4 年前

    您只需要在else语句中使用rest运算符调用push-to-tablesAndValues,并将值和id作为参数传递

    const response = {
      "data": {
        "Cstm_PF_ADG_URT_Disposition": {
          "child_welfare_placement_value": ""
        },
        "Cstm_PF_ADG_URT_Demographics": {
          "school_grade": "family setting",
          "school_grade_code": ""
        },
        "Cstm_Precert_Medical_Current_Meds": [
          {
            "med_name": "med1",
            "dosage": "10mg",
            "frequency": "daily"
          },
          {
            "med_name": "med2",
            "dosage": "20mg",
            "frequency": "daily"
          }
        ],
        "Cstm_PF_ADG_URT_Substance_Use": {
          "dimension1_comment": "dimension 1 - tab1",
          "Textbox1": "text - tab1"
        },
        "Cstm_PF_ADG_Discharge_Note": {
          "prior_auth_no_comm": "auth no - tab2"
        },
        "Cstm_PF_ADG_URT_Clinical_Plan": {
          "cca_cs_dhs_details": "details - tab2"
        },
        "container": {
          "Cstm_PF_Name": {
            "first_name": "same text for textbox - footer",
            "last_name": "second textbox - footer"
          },
          "Cstm_PF_ADG_URT_Demographics": {
            "new_field": "mapped demo - footer"
          },
          "grid2": [
            {
              "Cstm_PF_ADG_COMP_Diagnosis": {
                "diagnosis_label": "knee",
                "diagnosis_group_code": "leg"
              }
            },
            {
              "Cstm_PF_ADG_COMP_Diagnosis": {
                "diagnosis_label": "ankle",
                "diagnosis_group_code": "leg"
              }
            }
          ]
        },
        "submit": true
      }
    };
    
    function getNamesAndValues(data, id) {
      const tablesAndValues = [],
            res = data;
     
      Object.entries(res).map(([key, value]) => {
        const newKey = key.split('_')[0].toLowerCase();
        
        // console.log(newKey) // -> 'cstm'
        
        if (newKey === id) {
          tablesAndValues.push({
            table: key,
            values: value
          });
        } else {
          // I can log value and key and see what I want to push 
          // to the tablesAndValues array, but I can't seem to get 
          // how to push the nested items.
          
          // console.log(value);
          // console.log(key);
          
          tablesAndValues.push(...getNamesAndValues(value, id))
        }
      });
      
      return tablesAndValues;
    }
    
    console.log(getNamesAndValues(response.data, 'cstm'));

    或者用更短的方式

    function getNamesAndValues2(data, id) {
        return Object.entries(data).reduce((arr, [key, value]) => {
            arr.push(
                ...(key.split('_')[0].toLowerCase() === id ? [{ table: key, values: value }] : getNamesAndValues(value, id))
            );
            return arr
        }, []);
    }
    
        3
  •  1
  •   Joe Seifi    4 年前

    这是一个有效的版本。如果值是数组或对象,我递归地调用main函数。每次也传递计数数组的当前状态。

    function getNamesAndValues(data, id, tablesAndValues = []) {
      const res = data;
     
      Object.entries(res).map(([key, value]) => {
        const newKey = key.split('_')[0].toLowerCase();
        const item = res[key];
    
        if (newKey === id) {
          tablesAndValues.push({
            table: key,
            values: value
          });
        }
        
        if(Array.isArray(item)) {
            return item.map(el => getNamesAndValues(el, id, tablesAndValues));
        }
    
        if(typeof item === 'object') {
            return getNamesAndValues(item, id, tablesAndValues);
        }
    
      })
    
      return tablesAndValues;
    }
    
    console.log(getNamesAndValues(response.data, 'cstm'));
    
        4
  •  0
  •   Mulan    4 年前

    这是另一种使用发电机的方法-

    const keySearch = (t = [], q = "") =>
      filter(t, ([ k, _ ]) => String(k).startsWith(q))
    
    const r = 
      Array.from
        ( keySearch(response, "Cstm")
        , ([ table, values ]) =>
            ({ table, values })
        )
    
    console.log(r)
    
    [
      {
        table: 'Cstm_PF_ADG_URT_Disposition',
        values: { child_welfare_placement_value: '' }
      },
      {
        table: 'Cstm_PF_ADG_URT_Demographics',
        values: { school_grade: 'family setting', school_grade_code: '' }
      },
      {
        table: 'Cstm_Precert_Medical_Current_Meds',
        values: [ [Object], [Object] ]
      },
      {
        table: 'Cstm_PF_ADG_URT_Substance_Use',
        values: {
          dimension1_comment: 'dimension 1 - tab1',
          Textbox1: 'text - tab1'
        }
      },
      {
        table: 'Cstm_PF_ADG_Discharge_Note',
        values: { prior_auth_no_comm: 'auth no - tab2' }
      },
      {
        table: 'Cstm_PF_ADG_URT_Clinical_Plan',
        values: { cca_cs_dhs_details: 'details - tab2' }
      },
      {
        table: 'Cstm_PF_Name',
        values: {
          first_name: 'same text for textbox - footer',
          last_name: 'second textbox - footer'
        }
      },
      {
        table: 'Cstm_PF_ADG_URT_Demographics',
        values: { new_field: 'mapped demo - footer' }
      },
      {
        table: 'Cstm_PF_ADG_COMP_Diagnosis',
        values: { diagnosis_label: 'knee', diagnosis_group_code: 'leg' }
      },
      {
        table: 'Cstm_PF_ADG_COMP_Diagnosis',
        values: { diagnosis_label: 'ankle', diagnosis_group_code: 'leg' }
      }
    ]
    

    上面, keySearch filter -

    function* filter (t = [], test = v => v)
    { for (const v of traverse(t)){
        if (test(v))
          yield v
      }
    }
    

    traverse -

    function* traverse (t = {})
    { if (Object(t) === t)
        for (const [ k, v ] of Object.entries(t))
          ( yield [ k, v ]
          , yield* traverse(v)
          )
    }
    

    展开下面的代码段,在浏览器中验证结果-

    function* traverse (t = {})
    { if (Object(t) === t)
        for (const [ k, v ] of Object.entries(t))
          ( yield [ k, v ]
          , yield* traverse(v)
          )
    }
    
    function* filter (t = [], test = v => v)
    { for (const v of traverse(t)){
        if (test(v))
          yield v
      }
    }
    
    const keySearch = (t = [], q = "") =>
      filter(t, ([ k, _ ]) => String(k).startsWith(q))
    
    const response =
      {"data":{"Cstm_PF_ADG_URT_Disposition":{"child_welfare_placement_value":""},"Cstm_PF_ADG_URT_Demographics":{"school_grade":"family setting","school_grade_code":""},"Cstm_Precert_Medical_Current_Meds":[{"med_name":"med1","dosage":"10mg","frequency":"daily"},{"med_name":"med2","dosage":"20mg","frequency":"daily"}],"Cstm_PF_ADG_URT_Substance_Use":{"dimension1_comment":"dimension 1 - tab1","Textbox1":"text - tab1"},"Cstm_PF_ADG_Discharge_Note":{"prior_auth_no_comm":"auth no - tab2"},"Cstm_PF_ADG_URT_Clinical_Plan":{"cca_cs_dhs_details":"details - tab2"},"container":{"Cstm_PF_Name":{"first_name":"same text for textbox - footer","last_name":"second textbox - footer"},"Cstm_PF_ADG_URT_Demographics":{"new_field":"mapped demo - footer"},"grid2":[{"Cstm_PF_ADG_COMP_Diagnosis":{"diagnosis_label":"knee","diagnosis_group_code":"leg"}},{"Cstm_PF_ADG_COMP_Diagnosis":{"diagnosis_label":"ankle","diagnosis_group_code":"leg"}}]},"submit":true}}
    
    const result = 
      Array.from
        ( keySearch(response, "Cstm")
        , ([ table, values ]) =>
            ({ table, values })
        )
    
    console.log(result)