我正在尝试根据第一个键值对将文章数组拆分为子数组,并按顺序排列。
我研究了很多Stack Overflow帖子,并且我认为这是最适合我要完成的任务的
break array of objects into separate arrays based on a property
我知道通常会遇到关于reduce的问题,但是我被绊倒了,这就是我找不到答案的原因。
有什么不同:我不想将数组过滤到2个单独的类别(即“标记”和“视频”)中,而是让第一个数组全部是“标记” ”项,直到成为“视频”项为止,对所有“视频”项进行排列,直到下一个“标记”项为止,对所有“标记”项进行新的排列,直到下一个“视频”项,依此类推。>
以下是REPL再现了我想做的事情: REPL reproducing problem
数据如下:
export default [{
"type": "markup",
"element": "p",
"html": "blah"
}, {
"type": "markup",
"element": "p",
"html": "blah"
}, {
"type": "markup",
"element": "p",
"html": "blah"
}, {
"type": "embeddedVideo",
"element": "p",
"html": "embeddedWidget"
}, {
"type": "markup",
"element": "p",
"html": "blah"
},
{
"type": "markup",
"element": "p",
"html": "blah"
},
]
使用JavaScript reduce后,我想要的样子是:
[
[
{type: 'markup', element: 'p', html: 'blah' /*...*/ },
{type: 'markup', element: 'p', html: 'blah' /*...*/ },
{type: 'markup', element: 'p', html: 'blah' /*...*/ }
],
[
{type: 'embeddedVideo', /*...*/ }
],
[
{type: 'markup', element: 'p', html: 'blah' /*...*/ },
{type: 'markup', element: 'p', html: 'blah' /*...*/ },
{type: 'markup', element: 'p', html: 'blah' /*...*/ }
]
]
我到目前为止的是:
import articleBody from './articleBody.js';
function groupBy(arr, property) {
return arr.reduce((prop, x) => {
if (!prop[x[property]]) { prop[x[property]] = []; }
prop[x[property]].push(x);
return prop;
}, {});
}
let outputSample = groupBy(articleBody, "type");
console.log(outputSample)
此代码仅创建了2个数组(一个带有标记,一个带有视频),它没有记住原始数据的顺序,也没有根据顺序为所有数据组创建单独的数组。 / p>
解决此问题的最优雅方法是什么?如果您能正确地指导我,我将不胜感激。
答案 0 :(得分:2)
您可以使用Array#reduce
并检查累加器的最后一个元素。
var array = [{ type: "markup", element: "p", html: "blah" }, { type: "markup", element: "p", html: "blah" }, { type: "markup", element: "p", html: "blah" }, { type: "embeddedVideo", element: "p", html: "embeddedWidget" }, { type: "markup", element: "p", html: "blah" }],
grouped = array.reduce((r, o, i, a) => {
var last = r[r.length - 1];
if (!last || last[0].type !== o.type) {
r.push([o]);
} else {
last.push(o);
}
return r;
}, []);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 1 :(得分:1)
我知道for
不如reduce
酷,但它的可读性肯定更高:
const result = [[]];
let current = result[0], currentType = articleBody[0].type;
for(const content of articleBody) {
if(content.type === currentType) {
current.push(content);
} else {
result.push(current = [content]);
currentType = content.type;
}
}
答案 2 :(得分:1)
要使用reduce()
进行此操作,您只需关注最后看到的内容,然后将一个新数组(如果结果不同)推入结果,然后推入倒数第二个子数组。在眼睛上进行定期循环可能会更容易一些。
let tempArr = [{"type": "markup","element": "p","html": "blah"}, {"type": "markup","element": "p","html": "blah"}, {"type": "markup","element": "p","html": "blah"}, {"type": "embeddedVideo","element": "p","html": "embeddedWidget"}, {"type": "markup","element": "p","html": "blah"},{"type": "markup","element": "p","html": "blah"},]
let r = tempArr.reduce((a, c, i, self) => {
if (i === 0 || self[i-1].type !== c.type)
a.push([])
a[a.length - 1].push(c)
return a
}, [])
console.log(r)
答案 3 :(得分:0)
这是我的版本:)
const input = [{
"type": "markup",
"element": "p",
"html": "blah"
}, {
"type": "markup",
"element": "p",
"html": "blah"
}, {
"type": "markup",
"element": "p",
"html": "blah"
}, {
"type": "embeddedVideo",
"element": "p",
"html": "embeddedWidget"
}, {
"type": "markup",
"element": "p",
"html": "blah"
}];
const property = 'type';
const collection = [[]];
let found = input[0][property];
input.reduce((prev, next) => {
if (found === next[property]) {
prev.push(next);
return prev;
} else {
collection.push([next]);
found = next[property];
return collection[collection.length - 1];
}
}, collection[0]);
console.log('Collection', collection);
答案 4 :(得分:0)
此两步简化功能的说明:
如果类型与上一个条目不匹配或没有上一个 进入,将新行推到累加器上。
将当前对象添加到最新行。
const data = [{
"type": "markup",
"element": "p",
"html": "blah"
}, {
"type": "markup",
"element": "p",
"html": "blah"
}, {
"type": "markup",
"element": "p",
"html": "blah"
}, {
"type": "embeddedVideo",
"element": "p",
"html": "embeddedWidget"
}, {
"type": "markup",
"element": "p",
"html": "blah"
},
{
"type": "markup",
"element": "p",
"html": "blah"
},
];
const result = data.reduce((a, e) => {
if (!a[0] || e.type !== a[a.length-1].type) {
a.push([]);
}
a[a.length-1].push(e);
return a;
}, []);
console.log(result);