根据其偏移值将字符串分成多个部分

时间:2019-02-26 15:14:59

标签: javascript typescript

下面是文本,我想根据offsetlength分成多个部分。

  

您有任何疑问或意见,并希望与ABC联系吗?   请访问我们的客户支持页面。

以下是基于offsetlength提取文本的功能。

  let offset = '83';
  let length = '16';   

  getText(offset, length, text: string) {
    return text.substr(offset, length);
  }

上面的函数返回customer support

这样的实际问题

我必须拆分字符串的beforeafter文本。像下面这样的东西

text1:您有任何疑问或意见,并希望与ABC联系吗?请访问我们的

text2:客户支持

text3:页面

这可以实现吗?

2 个答案:

答案 0 :(得分:0)

您可能需要修改它以修剪多余的空格和/或标点符号。

let text = 'Do you have questions or comments and do you wish to contact ABC? Please visit our customer support page.'

let offset = 83;
let length = 16;

function getText(offset, length, text) {
    return { text1: text, text2: text.substr(offset, length), text3: text.substr(offset + length) };
}

let split = getText(offset, length, text);
console.log(split)

答案 1 :(得分:0)

您可以基于一个相关的问题breakAt来解决此问题,该问题将在多个切入点处分割字符串。这可以建立在将列表变成其连续对列表的基础上。 (即[2, 3, 5, 7] => [[2, 3], [3, 5], [5, 7]]。)这两个函数在您的应用程序中可能还有其他合理用途。

这里是用这种方式构建的实现:

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 getText = (offset, length, str) => breakAt([offset, offset+ length], str)

const str = "Do you have questions or comments and do you wish to contact ABC? Please visit our customer support page."
console.log(getText(83, 16, str))

我不清楚您首选的输出格式是什么。这只会根据您的offsetlengthstr生成一个包含文本前后,数组的数组。


更新

后续评论询问有关拆分多个子字符串的问题。这正是这种略微概括的意图。这个版本建立在breakAt的基础上,编写了一个新函数,该函数接受多个offset / length对,以便进一步分解单词。它不会尝试处理重叠的可能性;那将是呼叫者的监视。确实可以,但是可以对这些对进行排序,因此您不必按顺序提供它们。

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 = "Do you have questions or comments and do you wish to contact ABC? Please visit our customer support page."

console.log(breakWhere([
  {offset: 83, length: 16}, // "customer support"
  {offset: 12, length: 9},  // "questions"
  {offset: 25, length: 8},  // "comments"
], str))

slice调用只是为了避免使offset/length对的列表发生变异。如果不需要担心,可以将其删除。

另一个更新

另一个后续注释(该问题的最后一个,@stacks;下次启动一个新问题!)询问如何将输出格式化为跟踪纯文本与链接文本的节点。这是一个相当幼稚的版本:

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.reduce((a, {offset, length}) => [...a, offset, offset + length], []),
  str
)

const createNodes = (links, str) => {
  const sortedLinks = links.slice(0).sort(({offset: o1}, {offset: o2}) => o1 - o2)

  return breakWhere(sortedLinks, str).map((s, i) => i % 2 == 0 
    ? {data: s, type: 'text'}
    : {data: s, type: 'link', path: sortedLinks[(i - 1) / 2].path}
  ).filter(({data}) => data.length > 0)
}

const str = "Do you have questions or comments and do you wish to contact ABC? Please visit our customer support page."

const links = [
//  {offset: 0, length: 6, path: '/path/to/doYou'},
  {offset: 83, length: 16, path: '/path/to/custSupport'},
  {offset: 12, length: 9, path:  'path/to/questions'},
  {offset: 25, length: 8, path:  'path/to/comments'},
]


console.log(createNodes(links, str))

这将先前调用的简化版本包装为一个,该映射将备用字符串映射到type: 'text'type: 'link'对象,每个对象均具有data属性。链接也被赋予pathpath可能不适用于您的数据,您可以直接在代码中跳过它。

最后的filter调用是删除可能为空的文本节点。如果相邻两个链接,或者字符串的开头或结尾有一个链接,则将有一个空节点。您可以通过取消注释多余的link来查看此内容。如果删除filter调用,这将留下一个初始的空文本节点,可能不是所需的文本。

我将此版本称为天真,因为它无法处理多种可能性,最重要的是重叠的部分。这似乎要困难得多,而且对于您的项目可能从来没有必要。

注意

此方法的重要一点是它是分层的。我们没有建立一个一次性完成所有功能的函数,而是建立了辅助函数。 intoPairsbreakAt本身可能都有用。 breakWherecreateNodes可能更特定于此问题。我已经创建了createNodes,建立了breakWhere。将新功能放在旧功能之上很简单。

换句话说,这种设计融合了一些不断变化的需求的历史。就性能而言,它可能不是最佳的,不是因为存在任何严重的缺陷,而仅仅是因为它最初并不是在考虑最终需求的情况下创建的。有时值得回顾一下这样的代码,但这并不总是很重要。您将不得不确定此操作所使用的附加循环是否是您的应用程序严重关注的问题,还是只需要分层程度较低的代码。