按嵌套级别从嵌套对象属性中提取数组

时间:2019-07-15 03:44:14

标签: javascript typescript

我具有以下结构化,嵌套数据的JSON。

[
  {
    "id": "2e270ad7-90aa-41da-bb57-a777448f5906",
    "name": "First Level 1",
    "childValues": [
      {
        "id": "4cecbd28-fd06-4c2a-9b57-33d4a298675c",
        "name": "Second Level 1 "
      },
      {
        "id": "09893799-e21c-498f-96b4-e63e366a3c18",
        "name": "Second Level 2"
      }
    ]
  },
  {
    "id": "18889675-9d71-420e-84a6-3603af044b6c",
    "name": "First Level 2",
    "childValues": [
      {
        "id": "b7093ca1-5fed-4eb2-b934-637bfdc6c7da",
        "name": "Second Level 3"
      },
      {
        "id": "a3575212-1746-4dd3-ab52-4e37786c035c",
        "name": "Second Level 4"
      }
    ]
  },
  {
    "id": "71113ffb-62f0-4d76-941f-974be3cd35cb",
    "name": "First Level 3",
    "childValues": [
      {
        "id": "160570a5-29aa-4fdb-bb16-d9d7637d0177",
        "name": "Second Level 5",
        "childValues": [
          {
            "id": "2df28cb9-9ac4-478c-a2a4-6dc5206c983b",
            "name": "Third Level 1"
          },
          {
            "id": "a974cfac-1e2c-461c-ab64-0f5dd9d1cf1e",
            "name": "Third Level 2"
          }
        ]
      },
      {
        "id": "6e5947ea-2c47-4d2b-8ecd-6369c728e7db",
        "name": "Second Level 6"
      }
    ]
  }
]

我正在尝试基于嵌套级别从此嵌套数组结构中提取对象数组。例如,级别0只是给我返回数组中的所有基础对象,但是如果我要求级别1,则我试图在childValues属性下一次获取仅第二级嵌套对象的输出。数组,如下所示:

[
  {
    "id": "4cecbd28-fd06-4c2a-9b57-33d4a298675c",
    "name": "Second Level 1 "
  },
  {
    "id": "09893799-e21c-498f-96b4-e63e366a3c18",
    "name": "Second Level 2"
  },
  {
    "id": "b7093ca1-5fed-4eb2-b934-637bfdc6c7da",
    "name": "Second Level 3"
  },
  {
    "id": "a3575212-1746-4dd3-ab52-4e37786c035c",
    "name": "Second Level 4"
  },
  {
    "id": "160570a5-29aa-4fdb-bb16-d9d7637d0177",
    "name": "Second Level 5",
    "childValues": [
      {
        "id": "2df28cb9-9ac4-478c-a2a4-6dc5206c983b",
        "name": "Third Level 1"
      },
      {
        "id": "a974cfac-1e2c-461c-ab64-0f5dd9d1cf1e",
        "name": "Third Level 2"
      }
    ]
  },
  {
    "id": "6e5947ea-2c47-4d2b-8ecd-6369c728e7db",
    "name": "Second Level 6"
  }
]

如果我要求级别2,我应该只获取第三级对象:

[
  {
    "id": "2df28cb9-9ac4-478c-a2a4-6dc5206c983b",
    "name": "Third Level 1"
  },
  {
    "id": "a974cfac-1e2c-461c-ab64-0f5dd9d1cf1e",
    "name": "Third Level 2"
  }
]

我唯一想出的是如何以递归方式完全平整该结构,但不能指望如何提取特定级别。

private flat(array: any[]) {
  let result: any[] = [];
  array.forEach((a) => {
    result.push(a);
    if (Array.isArray(a.childValues)) {
      result = result.concat(this.flat(a.childValues));
    }
  });
  return result;
}

4 个答案:

答案 0 :(得分:1)

我能够通过以下功能实现这一目标。

function getArrayByNthLevelOfPropName(array, propName, levelToGet, currentLevel = 0) {
  let result = [];
  array.forEach((a) => {
    if (levelToGet === currentLevel) {
      result.push(a);
    }

    if (Array.isArray(a[propName]) && levelToGet !== currentLevel) {
      result = result.concat(getArrayByNthLevelOfPropName(a[propName], propName, levelToGet, ++currentLevel));
      currentLevel -= 1;
    }
  });

  return result;
}

答案 1 :(得分:1)

这是Shane Padgett函数的更简洁的版本:

const getArrayByNthLevel = (array, levelToGet, currentLevel=0) => array.reduce((retval, a) => {
        levelToGet === currentLevel
            ? retval.push(a)
            : Array.isArray(a.childValues)
                ? retval = retval.concat(getArrayByNthLevel(a.childValues, levelToGet, currentLevel + 1))
                : false
        return retval;
    }, []);

答案 2 :(得分:1)

您可以像这样使用flatMap

const input=[{id:"2e270ad7-90aa-41da-bb57-a777448f5906",name:"First Level 1",childValues:[{id:"4cecbd28-fd06-4c2a-9b57-33d4a298675c",name:"Second Level 1 "},{id:"09893799-e21c-498f-96b4-e63e366a3c18",name:"Second Level 2"}]},{id:"18889675-9d71-420e-84a6-3603af044b6c",name:"First Level 2",childValues:[{id:"b7093ca1-5fed-4eb2-b934-637bfdc6c7da",name:"Second Level 3"},{id:"a3575212-1746-4dd3-ab52-4e37786c035c",name:"Second Level 4"}]},{id:"71113ffb-62f0-4d76-941f-974be3cd35cb",name:"First Level 3",childValues:[{id:"160570a5-29aa-4fdb-bb16-d9d7637d0177",name:"Second Level 5",childValues:[{id:"2df28cb9-9ac4-478c-a2a4-6dc5206c983b",name:"Third Level 1"},{id:"a974cfac-1e2c-461c-ab64-0f5dd9d1cf1e",name:"Third Level 2"}]},{id:"6e5947ea-2c47-4d2b-8ecd-6369c728e7db",name:"Second Level 6"}]}];

const getLevel = (arr = [], required, current = 0) =>
    required === current 
      ? arr
      : arr.flatMap(a => getLevel(a.childValues, required, current + 1))

console.log("Second Level: \n ", getLevel(input, 1))
console.log("Third Level: \n ", getLevel(input, 2))

如果不支持flatMap,则可以使用

[].concat(...arr.map(a => getLevel(a.childValues, required, current + 1)))

答案 3 :(得分:0)

以下应该有效:

var data = [
  {
    "id": "2e270ad7-90aa-41da-bb57-a777448f5906",
    "name": "First Level 1",
    "childValues": [
      {
        "id": "4cecbd28-fd06-4c2a-9b57-33d4a298675c",
        "name": "Second Level 1"
      },
      {
        "id": "09893799-e21c-498f-96b4-e63e366a3c18",
        "name": "Second Level 2"
      }
    ]
  },
  {
    "id": "18889675-9d71-420e-84a6-3603af044b6c",
    "name": "First Level 2",
    "childValues": [
      {
        "id": "b7093ca1-5fed-4eb2-b934-637bfdc6c7da",
        "name": "Second Level 3"
      },
      {
        "id": "a3575212-1746-4dd3-ab52-4e37786c035c",
        "name": "Second Level 4"
      }
    ]
  },
  {
    "id": "71113ffb-62f0-4d76-941f-974be3cd35cb",
    "name": "First Level 3",
    "childValues": [
      {
        "id": "160570a5-29aa-4fdb-bb16-d9d7637d0177",
        "name": "Second Level 5",
        "childValues": [
          {
            "id": "2df28cb9-9ac4-478c-a2a4-6dc5206c983b",
            "name": "Third Level 1"
          },
          {
            "id": "a974cfac-1e2c-461c-ab64-0f5dd9d1cf1e",
            "name": "Third Level 2"
          }
        ]
      },
      {
        "id": "6e5947ea-2c47-4d2b-8ecd-6369c728e7db",
        "name": "Second Level 6"
      }
    ]
  }
];

function getData(data, targetLevel, currentLevel = 0) {
    // If this is the target level, then extract the
    // data we need from each item, and return the array
    if (currentLevel == targetLevel) {
        return data;
    }
    // Otherwise, run a map over the items, and if they have
    // 'childValues', then recurs, but increment the value of
    // 'current level' it will be iterating on
    // Because 'map' will return array of array, merge them
    // to a single array
    return [].concat(...data.map(item => {
        if (item.childValues) {
            return getData(item.childValues, targetLevel, currentLevel + 1);
        };
        return [];
    }));
}

document.getElementById("dataLevel0").innerHTML = JSON.stringify(getData(data, 0), null, 4);
document.getElementById("dataLevel1").innerHTML = JSON.stringify(getData(data, 1), null, 4);
document.getElementById("dataLevel2").innerHTML = JSON.stringify(getData(data, 2), null, 4);
<div>
Level 1:
</div>
<pre id="dataLevel0">
</pre>
<div>
Level 2:
</div>
<pre id="dataLevel1">
</pre>
<div>
Level 3:
</div>
<pre id="dataLevel2">
</pre>