基于下面的data
,我需要按其offset
和length
值细分文本。
const data = {
"text": "Do you have questions or comments and do you wish to contact ABC? Please visit our customer support page.",
"inlineEntityRanges": [{
"type": "LINK",
"offset": 83,
"length": 16,
"data": {
"target": "_self",
"url": "/index.htm"
}
}]
}
使用以下代码段,我可以在任意特定位置细分文本。
那是什么问题?
我想按以下格式细分文本,并为其分配动态类型。
如何分配类型?
如果响应中未提及任何类型,则其默认类型应为text
。如果响应中存在类型值,则应分配相应的值。
所以最终的期望输出应该是这样的,
[{
data: 'Do you have questions or comments and do you wish to contact ABC? Please visit our',
type: 'text'
},
{
data: 'customer support',
type: 'link'
},
{
data: 'page.',
type: '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 intoPairs = xs => xs.slice(1).map((x, i) => [xs[i], x])
const breakAt = (places, str) => intoPairs([0, ...places, str.length]).map(
([a, b]) => str.substring(a, b)
)
const breakWhere = (words, str) => breakAt(
words.slice(0).sort(({
offset: o1
}, {
offset: o2
}) => o1 - o2).reduce(
(a, {
offset,
length
}) => [...a, offset, offset + length], []
),
str
)
const str = data.text;
const inlineRanges = data.inlineEntityRanges
inlineRanges.forEach(range => {
console.log(breakWhere([{
offset: range.offset,
length: range.length
}], str));
})
答案 0 :(得分:0)
尝试以下解决方案:
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)))
答案 1 :(得分:0)
另一种可能性是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
:{ {1}})
如果您不希望这种扩展行为,可以通过替换来更改
({offset, length ...rest}) => ({...rest})
与此:
: {data: s, ...slim(nodes[(i - 1) / 2])}
(此时您也可以删除 : {data: s, type: nodes[(i - 1) / 2].type}
。)
这可能就是您想要做的,但是我写的版本保留了所有可能对下游有用的信息。
(一件愚蠢的事情:“文本” /“样式” /“ LINK”的大写字母差异确实困扰着我不知道的我的某些OCD部分。看在天上,将其更改为“链接”。;- )