如何更改 reduce 函数以产生不同的结果
how to alter reduce function so it produce different result
我有这个数组:
data: [
'+section1+',
'big text 1 here.',
'big text 2 here followed by list:',
'-this is list item;',
'-this is another list item;',
'+section2+',
'big text 3 here followed by list:',
'-this is list item;',
'-this is another list item;',
'-this is another list item;',
'+section3+',
'big text 4 here.'
],
我想将该数组转换为
"data": [
{
section: "section1",
content: [
{
"text": "big text 1 here.",
"list": []
},
}
{
"text": "big text 2 here followed by list:",
"list": [
"-this is list item;",
"-this is another list item;"
]
},
]
}
{
section: "section2"
content:[
{
"text": "big text 3 here followed by list:",
"list": [
"-this is list item;",
"-this is another list item;",
"-this is another list item;"
]
},
]
}
{
section: "section3",
content: [
{
"text": "big text 4 here.",
"list": []
}
]
}
]
我有关于 that:
的代码
interface DataItem {
text: string
list: string[]
}
function isListItem(item: string): boolean {
return item.startsWith('-') && item.endsWith(';')
}
const transformedData = data.reduce<DataItem[]>((acc, item) => {
// if item is list item
if (isListItem(item)) {
// get last DataItem from acc
const lastDataItem = acc[acc.length - 1]
// and use it as list item's parent
if (lastDataItem) {
lastDataItem.list.push(item)
} else {
console.error(`Parent text not found for list item ${item}`)
}
return acc
}
// if item is not list item, use it as new parent/DataItem
const dataItem: DataItem = {
text: item,
list: []
}
return [...acc, dataItem]
}, [])
它缺少的是忽略部分。有什么想法可以修改该 reduce 函数以产生预期结果吗?
为了确定一个部分,我想出了这个函数:
function isSection(item: string): boolean {
return item.startsWith('+') && item.endsWith('+')
}
应该这样做
const data= [
'+section1+',
'big text 1 here.',
'big text 2 here followed by list:',
'-this is list item;',
'-this is another list item;',
'+section2+',
'big text 3 here followed by list:',
'-this is list item;',
'-this is another list item;',
'-this is another list item;',
'+section3+',
'big text 4 here.'
]
const result = data.reduce((res, item) =>{
if(item.startsWith('+')){
const section = item.substring(1, item.length -1)
return[
...res,
{
section,
content: []
}
]
}
const lastSectionIndex = res.length - 1
if(item.startsWith('-')){
const lastSection = res[lastSectionIndex]
const lastContent = lastSection.content[lastSection.content.length -1]
res[res.length - 1].content[lastSection.content.length -1].list.push(item.substring(1, item.length -1))
return res
}
res[lastSectionIndex].content.push({text: item, list:[]})
return res;
},[])
console.log(result)
我将使用我对 OP 的另一个(以前问过的)问题的回答中的相同方法... ... 并根据 OP 的新要求进行调整。
因此人们会留在reduce
based approach which does not depend on outer scope references for keeping track of the currently to be built/aggregated property but instead makes this information part of the reducer function's first parameter, the previousValue
which serves as an accumulator/collector object。
至于 OP 的任务,此收集器将具有 2 个属性,sectionKey
和 result
,其中前者保存当前处理的 属性 名称的状态,以及后者是以编程方式构建的 result
-array of section-items.
function aggregateStructuredTextItem(
{ sectionKey = '', result = [] },
item
) {
// try to retrieve the section specific text.
let text = (item.match(/^\+\s*(.*?)\s*\+$/) || [])[1] ?? null;
if (
(text !== null) &&
(text !== sectionKey)
) {
// keep track of the currently processed section.
sectionKey = text;
// create and collect new section entry.
result.push({ section: text, content: [] });
} else {
// access the currently processed section.
const section = result.at(-1);
// try to retrieve the list specific text.
text = (item.startsWith('-') && item.slice(1));
if (text !== false) {
// push list specific text into
// the most recent content list.
section.content.at(-1).list.push(text);
} else {
// create a content item and push it
// into the most recent section content.
section.content.push({ text: item, list: [] });
}
}
return { sectionKey, result };
}
const textData = [
'+section1+',
'big text 1 here.',
'big text 2 here followed by list:',
'-this is list item;',
'-this is another list item;',
'+section2+',
'big text 3 here followed by list:',
'-this is list item;',
'-this is another list item;',
'-this is another list item;',
'+section3+',
'big text 4 here.'
];
const structuredTextData = textData
.reduce(aggregateStructuredTextItem, { result: [] })
.result;
console.log({ textData, structuredTextData });
.as-console-wrapper { min-height: 100%!important; top: 0; }
我有这个数组:
data: [
'+section1+',
'big text 1 here.',
'big text 2 here followed by list:',
'-this is list item;',
'-this is another list item;',
'+section2+',
'big text 3 here followed by list:',
'-this is list item;',
'-this is another list item;',
'-this is another list item;',
'+section3+',
'big text 4 here.'
],
我想将该数组转换为
"data": [
{
section: "section1",
content: [
{
"text": "big text 1 here.",
"list": []
},
}
{
"text": "big text 2 here followed by list:",
"list": [
"-this is list item;",
"-this is another list item;"
]
},
]
}
{
section: "section2"
content:[
{
"text": "big text 3 here followed by list:",
"list": [
"-this is list item;",
"-this is another list item;",
"-this is another list item;"
]
},
]
}
{
section: "section3",
content: [
{
"text": "big text 4 here.",
"list": []
}
]
}
]
我有关于 that:
的代码interface DataItem {
text: string
list: string[]
}
function isListItem(item: string): boolean {
return item.startsWith('-') && item.endsWith(';')
}
const transformedData = data.reduce<DataItem[]>((acc, item) => {
// if item is list item
if (isListItem(item)) {
// get last DataItem from acc
const lastDataItem = acc[acc.length - 1]
// and use it as list item's parent
if (lastDataItem) {
lastDataItem.list.push(item)
} else {
console.error(`Parent text not found for list item ${item}`)
}
return acc
}
// if item is not list item, use it as new parent/DataItem
const dataItem: DataItem = {
text: item,
list: []
}
return [...acc, dataItem]
}, [])
它缺少的是忽略部分。有什么想法可以修改该 reduce 函数以产生预期结果吗?
为了确定一个部分,我想出了这个函数:
function isSection(item: string): boolean {
return item.startsWith('+') && item.endsWith('+')
}
应该这样做
const data= [
'+section1+',
'big text 1 here.',
'big text 2 here followed by list:',
'-this is list item;',
'-this is another list item;',
'+section2+',
'big text 3 here followed by list:',
'-this is list item;',
'-this is another list item;',
'-this is another list item;',
'+section3+',
'big text 4 here.'
]
const result = data.reduce((res, item) =>{
if(item.startsWith('+')){
const section = item.substring(1, item.length -1)
return[
...res,
{
section,
content: []
}
]
}
const lastSectionIndex = res.length - 1
if(item.startsWith('-')){
const lastSection = res[lastSectionIndex]
const lastContent = lastSection.content[lastSection.content.length -1]
res[res.length - 1].content[lastSection.content.length -1].list.push(item.substring(1, item.length -1))
return res
}
res[lastSectionIndex].content.push({text: item, list:[]})
return res;
},[])
console.log(result)
我将使用我对 OP 的另一个(以前问过的)问题的回答中的相同方法...
因此人们会留在reduce
based approach which does not depend on outer scope references for keeping track of the currently to be built/aggregated property but instead makes this information part of the reducer function's first parameter, the previousValue
which serves as an accumulator/collector object。
至于 OP 的任务,此收集器将具有 2 个属性,sectionKey
和 result
,其中前者保存当前处理的 属性 名称的状态,以及后者是以编程方式构建的 result
-array of section-items.
function aggregateStructuredTextItem(
{ sectionKey = '', result = [] },
item
) {
// try to retrieve the section specific text.
let text = (item.match(/^\+\s*(.*?)\s*\+$/) || [])[1] ?? null;
if (
(text !== null) &&
(text !== sectionKey)
) {
// keep track of the currently processed section.
sectionKey = text;
// create and collect new section entry.
result.push({ section: text, content: [] });
} else {
// access the currently processed section.
const section = result.at(-1);
// try to retrieve the list specific text.
text = (item.startsWith('-') && item.slice(1));
if (text !== false) {
// push list specific text into
// the most recent content list.
section.content.at(-1).list.push(text);
} else {
// create a content item and push it
// into the most recent section content.
section.content.push({ text: item, list: [] });
}
}
return { sectionKey, result };
}
const textData = [
'+section1+',
'big text 1 here.',
'big text 2 here followed by list:',
'-this is list item;',
'-this is another list item;',
'+section2+',
'big text 3 here followed by list:',
'-this is list item;',
'-this is another list item;',
'-this is another list item;',
'+section3+',
'big text 4 here.'
];
const structuredTextData = textData
.reduce(aggregateStructuredTextItem, { result: [] })
.result;
console.log({ textData, structuredTextData });
.as-console-wrapper { min-height: 100%!important; top: 0; }