将动态类型分配给字符串

问题描述 投票:1回答:2

根据下面的data,我需要分解其offsetlength值的文本。

const data = {
  "text": "This is sample text",
  "range": [{
    "type": "LINK",
    "offset": 0,
    "length": 16,
    "data": {
      "target": "_self",
      "url": "/index.htm"
    }
  }]
}

使用下面的代码片段,我可以在任何特定点分解文本。

所以有什么问题 ?

我希望按以下格式细分文本,并为其分配动态类型。

如何分配类型?

如果响应中没有提到类型,则默认类型应为text。如果响应中存在类型值,则应分配相应的值。

javascript typescript
2个回答
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)))

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))

它返回的每个节点的数据多于您的请求,包括styleurltarget节点。 (这有一个奇怪之处:我把urltarget节点提升了一个级别,因为他们的父节点是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部分我不知道我有。为了天堂的缘故,将其改为“链接”。;-))

© www.soinside.com 2019 - 2024. All rights reserved.