如何解决将数组转换为多个数组 使用 While 循环的解决方案使用正则表达式的解决方案
我正在尝试操作一个数组,但似乎无法将其转换成我想要的形式。
这是数组:
const children = [
{ type: 'span' },{ type: 'br' },{ type: 'span' },]
所以挑战是创建一个数组数组。每当有 2 个或更多连续的 br
值时,这表示一个数组的结束位置和下一个数组的开始位置。所以我试图做到这一点:
[
[{type: 'span'},{type: 'br'},{type: 'span'}],[{type: 'span'}],[{type: 'span'},{type: 'span'}]
]
想知道 reduce
是否比 forEach
更好?
解决方法
它有点懒,你可能想根据你的数据选择 \n
以外的分隔符,但是
const children = [
'span','br','span','span'
]
console.log(children.join("\n").split(/(?:\nbr){2,}\n/).map(p => p.split("\n")))
当然有效...
,console.log(
children
.map(({ type: t }) => t) // to array of strings
.map(t => t === 'br' ? ' ' : t) // br => ' ' for using split() and trim()
.join('') // to long string,.split(' ') // split by 2 'br'
.map(r => r.trim()) // remove leading & trailing 'br's
.map(r => r
.replace(' ','|br|') // restore 'br'
.split('|') // split to array
.map(r => ({type : r})) // restore structure
)
);
,
我不是 100% 确定这有效,我觉得它可以更简洁一些,但这里尝试使用 reduce:
const children = [{"type":"span"},{"type":"br"},{"type":"span"},{"type":"span"}];
const is_br = (item) => item?.type === 'br';
const result = children.reduce(
(acc,val,i,{ [i - 1]: prev,[i + 1]: next }) => {
if(!is_br(prev) && is_br(val) && is_br(next))
acc.push([]);
if(is_br(val) && (is_br(prev) || is_br(next)))
return acc;
acc[acc.length - 1].push(val);
return acc;
},[[]]
);
console.log(result);
您的代码的可能工作(或接近)版本:
const children = [{"type":"span"},{"type":"span"}];
let paragraphs = []
let elements = []
let flag = false
children.forEach((child,idx) => {
if (child.type !== 'br') {
flag = false
elements.push(child)
} else {
if (flag) {
if(elements.length > 1) {
paragraphs.push(elements.splice(0,elements.length - 1))
}
elements = []
} else {
elements.push(child)
flag = true
}
}
if(idx === children.length - 1 && elements.length > 0)
paragraphs.push(elements)
});
console.log(paragraphs);
使用 While 循环的解决方案。
-
有两个变量,第一个是计数器
i
,第二个是temp
,用于帮助存储不同的数组切片。 -
接下来,有一个嵌套的 while 循环。第一个是简单的循环,第二个循环是跳过所有连续的
"br"
。 -
有一个
flag
来检查第二个while
循环是否运行。-
如果这样做意味着我们现在需要将
temp
的内容推入结果数组res
并清空temp
。 -
如果没有,我们需要继续推动
temp
。
-
这里还有一些检查来处理一些边缘情况。
const children = [{type:"span"},{type:"br"},{type:"span"},{type:"span"}];
const res = [];
let i = 0;
let temp = [];
while (i < children.length) {
let flag = false;
while (i < children.length && children[i].type === "br" && children[i + 1]?.type === "br") {
i++;
flag = true;
}
if (flag) { res.push(temp); temp = []; i++; }
if (i >= children.length) break;
temp.push(children[i]);
i++;
}
if (temp.length > 0) res.push(temp);
console.log(JSON.stringify(res));
使用正则表达式的解决方案
(灵感来自 Ralkov 的解决方案)
const
children = [{type:"span"},{type:"span"}],res = children
.map(({ type }) => `${type} `)
.join("")
.replace(/(?:br\s){2,}/g," ")
.trim()
.split(" ")
.map((s) => s.split(",").map((type) => ({ type })));
console.log(JSON.stringify(res));
你可以减少数组。
const
children = [{ type: 'span' },{ type: 'br' },{ type: 'span' },{ type: 'span' }],separator = 'br',result = children.reduce((r,o,a) => {
if (o.type === separator) {
if (a[i - 1]?.type === separator) {
if (r[r.length - 1].length) r.push([]);
return r;
} else if (a[i + 1]?.type === separator) return r;
}
r[r.length - 1].push(o.type);
return r;
},[[]]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
这里有一个 1) 将您的对象数组转换为字符串,2) 在多个 b
上拆分和 3) 将拆分的数组转换回对象:
const children = [
{ type: "span" },{ type: "br" },{ type: "span" },];
const map = { s: "span",b: "br" };
console.log(
children
.reduce((s,o) => (s += o.type[0]),"") // convert obj arr to string
.split(/b{2,}/) // splits string on 2 or more 'b's
.map((s) => { // convert split strings back into obj arr
const res = [];
for (const ch of s) {
res.push({ type: map[ch] });
}
return res;
})
);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。