根据下面的data
,我需要分解其offset
和length
值的文本。
const data = {
"text": "This is sample text",
"range": [{
"type": "LINK",
"offset": 0,
"length": 16,
"data": {
"target": "_self",
"url": "/index.htm"
}
}]
}
使用下面的代码片段,我可以在任何特定点分解文本。
所以有什么问题 ?
我希望按以下格式细分文本,并为其分配动态类型。
如何分配类型?
如果响应中没有提到类型,则默认类型应为text
。如果响应中存在类型值,则应分配相应的值。
尝试以下解决方案:
let inlineEntity = [];
const data = {
"text": "Do you have questions or comments and do you wish to contact ABC? Please visit our customer support page.",
"inlineStyleRanges": [{
"style": "BOLD",
"offset": 12,
"length": 20,
"type": "style"
}],
"inlineEntityRanges": [{
"type": "LINK",
"offset": 83,
"length": 16,
"data": {
"target": "_self",
"url": "/index.htm"
}
}]
}
const MARKER = '||||';
function breakByRanges(ranges, text, tempString) {
const result = [];
ranges.forEach((styleRange) => {
const { offset, length, type } = styleRange;
const str = text.slice(offset, offset + length + 1);
tempString = tempString.replace(str, MARKER);
result.push({ data: str, type });
})
return { result, tempString };
}
function breakData(data, ranges) {
const { inlineStyleRanges, inlineEntityRanges, text } = data;
const result = [];
let tempText = text;
let { result: styleResult, tempString: styleTempText } = breakByRanges(inlineStyleRanges, text, tempText);
tempText = styleTempText;
result.push(...styleResult);
let { result: entityResult, tempString: entityTempText } = breakByRanges(inlineEntityRanges, text, styleTempText);
tempText = entityTempText;
result.push(...entityResult);
let orderNumber = 0;
const textItems = tempText.split(MARKER).map((data, index) => {
if (result[index]) {
result[index].order = orderNumber + index + 1;
}
const resultData = { data, type: 'text', order: orderNumber + index };
orderNumber += 1;
return resultData;
});
result.push(...textItems);
return result.sort((first, second) => first.order - second.order).map((item) => ({ data: item.data, type: item.type }));
}
console.log(JSON.stringify(breakData(data)))
另一种可能性,即将my answer改编为您之前的问题,将辅助函数合并到主要函数中并更新为新的组合输入格式是:
const breakData = (data) => {
const nodes = (data.inlineStyleRanges || [])
.concat(data.inlineEntityRanges || [])
.sort(({offset: o1}, {offset: o2}) => o1 - o2)
const str = data.text || ''
const indices = [
0,
...nodes.reduce((a, {offset, length}) => [...a, offset, offset + length], []),
str.length
]
const slim = ({offset, length, data, ...rest}) => ({...rest, ...data})
return indices.slice(1).map((x, i) => [indices[i], x])
.map(([a, b]) => str.substring(a, b))
.map((s, i) => i % 2 == 0
? {data: s, type: 'text'}
: {data: s, ...slim(nodes[(i - 1) / 2])}
).filter(({data}) => data.length > 0)
}
const data = {"text": "Do you have questions or comments and do you wish to contact ABC? Please visit our customer support page.", "inlineEntityRanges": [{"data": {"target": "_self", "url": "/index.htm"}, "length": 16, "offset": 83, "type": "LINK"}], "inlineStyleRanges": [{"length": 21, "offset": 12, "style": "BOLD", "type": "style"}]}
console.log(breakData(data))
它返回的每个节点的数据多于您的请求,包括style
,url
和target
节点。 (这有一个奇怪之处:我把url
和target
节点提升了一个级别,因为他们的父节点是data
,它与输出中的data
相冲突;我不是特别喜欢这个。如果你对text
感到满意的话输出节点而不是data
,然后你可以在三元组中替换它,并将其用于slim
:({offset, length ...rest}) => ({...rest})
)
如果您不想要此扩展行为,可以通过替换来更改它
: {data: s, ...slim(nodes[(i - 1) / 2])}
有了这个:
: {data: s, type: nodes[(i - 1) / 2].type}
(此时你也可以删除slim
。)
这可能是你想要做的,但是我编写的版本保留了下游可能有用的各种信息。
(一个愚蠢的事情:“文本”/“风格”/“链接”大写差异真的困扰我的一些OCD部分我不知道我有。为了天堂的缘故,将其改为“链接”。;-))