Javascript 从多个嵌套数组创建新的数据对象集
我有一个复杂的数据结构,有多个嵌套数组 以下是目前的结构Javascript 从多个嵌套数组创建新的数据对象集,javascript,arrays,typescript,multidimensional-array,Javascript,Arrays,Typescript,Multidimensional Array,我有一个复杂的数据结构,有多个嵌套数组 以下是目前的结构 var contentData = { data: { content: [ { type: "column", sections: [ { sub: [ { type: "heading-1", text: "Heading Text"
var contentData = {
data: {
content: [
{
type: "column",
sections: [
{
sub: [
{
type: "heading-1",
text: "Heading Text"
}
]
}
]
},
{
type: "acc-item",
sections: [
{
sub: [
{
type: "heading-1",
text: "Heading Text"
},
{
type: "ordered-item",
text: "Item 1"
},
{
type: "unordered-item",
text: "Item 2"
}
]
}
]
},
{
type: "acc-item",
sections: [
{
sub: [
{
type: "heading-1",
text: "Heading Text 2"
}
]
}
]
}
]
}
}
所以我想要的是
有序项和无序项
分组到一个新对象中,如{type:'list',items:[所有列表项]}
sub
中的所有项目,并将其推送到新对象embedded
,它应该放置在根级别,如下所示
{type:“acc项目”,嵌入:[{type:“heading-1”,text:“heading-text 2”}]}代码>
acc项目
,但不能分组已订购项目和未订购项目
所以我的最终预期结果应该是这样的
[{
"type": "column",
"embedded": [
{
"type": "heading-1",
"text": "Heading Text"
}
]
},
{
"type": "acc-group",
"items": [
{
"type": "acc-item",
"embedded": [
{
"type": "heading-1",
"text": "Heading Text"
},
{
"type": "list",
"items": [
{
"type": "ordered-item",
"text": "Item 1"
},
{
"type": "unordered-item",
"text": "Item 2"
}
]
}
]
},
{
"type": "acc-item",
"embedded": [
{
"type": "heading-1",
"text": "Heading Text 2"
}
]
}
]
}]
下面是我的代码
var组,contentData={data:{content:[{type:“column”,sections:[{sub:[{type:“heading-1”,text:“heading-text”}]}},{type:“acc-item”,sections:[{sub:[{type:“heading-1”,text:“heading-text”},{type:“item 1”},{type:“无序项”,text:“item:“item 2”}},{type:“acc-item:{sub type:[{type:“heading-1”,“heading-text:”heading-text:}},类型=[“列表”、[“已订购项目”、“未订购项目”]、[“手风琴”、[“acc项目”]];
var result=contentData.data.content.reduce((r,o)=>{
var type=(types.find({1:values})=>values.indexOf(o.type)>-1)|{}[0];
如果(!类型){
r、 推(o);
组=未定义;
返回r;
}
如果(!group | | group.type!==type){
组={type,items:[]};
r、 推(组);
}
分组项目推送(o);
返回r;
}, []);
document.body.innerHTML=''+JSON.stringify(结果,null'')+''代码>和方法非常适合这种情况
const groupedData = contentData.data.content.reduce((acc, cur) => {
//Check if this indexed array already exists, if not create it.
const currentArray = (acc[`${cur.type}-group`] && acc[`${cur.type}-group`].items) || [];
return {
...acc,
[`${cur.type}-group`]: {
type: `${cur.type}-group`,
items: [...currentArray, cur]
}
}
}, {});
你是对的,这是一种复杂的逻辑
我建议您确实需要为此进行一些单元测试,并尝试将其分解成不同的部分
我想我会这么做的
1。按类型分组以创建分组。
实际上,我正在创建一个您在这里要求的更通用的解决方案。也就是说,我不仅仅是对“acc项目”进行分组,而是对所有项目进行分组
我快速搜索了“array group by javascript”,它给出了使用array.reduce的建议,让我们这样做吧
function flattenSectionsAndSubs(item) {
return {
type: item.type,
subs: item.sections.reduce((acc, cur) => ([...acc, ...cur.sub]), [])
};
}
function partition(array, isValid) {
return array.reduce(([pass, fail], elem) => {
return isValid(elem) ? [[...pass, elem], fail] : [pass, [...fail, elem]];
}, [[], []]);
}
const listTypes = ['ordered-item', 'unordered-item'];
function createEmbeddedFromItem(item) {
const [lists, nonLists] = partition(item.subs, (v) => listTypes.includes(v.type);
return {
type: item.type,
embedded: [
...nonLists,
{
type: "list",
items: lists
}
]
}
}
2。现在,对于这些项目中的每一项,我们需要查看它们的子项,并仅对列表项目进行分组。
为此,我们基本上希望找到所有的`item->sections->sub->type,并将它们过滤到两个数组中。在谷歌上快速搜索如何使用过滤器创建两个数组
不过,首先,我们需要将节->子节的内容展平,所以让我们这样做吧
function flattenSectionsAndSubs(item) {
return {
type: item.type,
subs: item.sections.reduce((acc, cur) => ([...acc, ...cur.sub]), [])
};
}
function partition(array, isValid) {
return array.reduce(([pass, fail], elem) => {
return isValid(elem) ? [[...pass, elem], fail] : [pass, [...fail, elem]];
}, [[], []]);
}
const listTypes = ['ordered-item', 'unordered-item'];
function createEmbeddedFromItem(item) {
const [lists, nonLists] = partition(item.subs, (v) => listTypes.includes(v.type);
return {
type: item.type,
embedded: [
...nonLists,
{
type: "list",
items: lists
}
]
}
}
我将复制粘贴分区函数到:
把这一切放在一起,我们就得到了。
const contentData={
数据:{
内容:[{
键入:“列”,
章节:[{
分:[{
类型:“标题-1”,
文本:“标题文本”
}]
}]
},
{
类型:“acc项目”,
章节:[{
分:[{
类型:“标题-1”,
文本:“标题文本”
},
{
类型:“订购物品”,
案文:“项目1”
},
{
类型:“无序项”,
案文:“项目2”
}
]
}]
},
{
类型:“acc项目”,
章节:[{
分:[{
类型:“标题-1”,
正文:“标题正文2”
}]
}]
}
]
}
}
函数分区(数组,isValid){
返回数组.reduce([pass,fail],elem)=>{
返回是否有效(elem)[
[…通过,要素],失败
]:[pass,[…fail,elem];
}, [
[],
[]
]);
}
功能分区和子分区(项目){
返回{
类型:item.type,
subs:item.sections.reduce((acc,cur)=>([…acc,…cur.sub]),[])
};
}
const listTypes=['ordered-item','unordered item'];
函数createEmbeddedFromItem(项){
const[list,nonlist]=分区(item.subs,(v)=>listTypes.includes(v.type));
返回{
类型:item.type,
嵌入式:[
…非名单,
{
键入:“列表”,
项目:清单
}
]
}
}
const groupedData=contentData.data.content.reduce((acc,cur)=>{
//检查此索引数组是否已存在,如果不存在,请创建它。
const currentArray=(acc[`cur.type}-group`]和&acc[`cur.type}-group`].items)|[];
const flatteditem=扁平部分和分段(cur);
const embeddedItem=createEmbeddedFromItem(FlattedItem);
返回{
…acc,
[`${cur.type}-group`]:{
类型:`${cur.type}-group`,
items:[…currentArray,embeddedItem]
}
}
}, {});
console.log(groupedData)代码>您可以存储最后一个项数组以及最后一个嵌入数组,并在找到列类型之前使用它们
var contentData={data:{content:[{type:“column”,sections:[{sub:[{type:“heading-1”,text:“heading-text”}]},{type:“acc-item”,sections:[{sub:[{type:“heading-1”,text:“heading-text”},{type:“ordered-item”},{type:“unordered item”,text:“item:“item 2”}]},{type:“acc-item:[{sub sub[{类型:“标题-1”,文本:“标题文本2”}]}]}},
列表=[“已订购项目”、“未订购项目”],
lastItems,lastEmbedded,
result=contentData.data.content.reduce((r,{type,sections})=>{
如果(类型=='列'){
r、 push({type,embedded:sections.reduce((q,{sub})=>q.concat(sub),[]));
lastItems=未定义;
lastEmbedded=未定义;
返回r;
}
if(!lastItems)r.push({type:“acc group”,items:lastItems=[]});
lastItems.push(…sections.map({sub})=>({
类型,
嵌入式:sub.reduce((q,o)=>{