【问题标题】:Split string into multiple parts based on its offset value根据偏移值将字符串拆分为多个部分
【发布时间】:2019-03-05 23:26:04
【问题描述】:

以下是正文,我想根据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: 页面

这可以实现吗?

【问题讨论】:

    标签: javascript typescript


    【解决方案1】:

    您可以将此问题建立在相关问题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。将新功能叠加在旧功能之上很简单。

    换句话说,设计本身就包含了一些需求变化的历史。就性能而言,它可能不是最佳的,不是因为任何严重的缺陷,而只是因为它最初不是在考虑最终需求的情况下创建的。有时值得回过头来重新思考这样的代码,但这并不总是很重要。您必须确定此使用的额外循环是否严重影响您的应用程序,或者您是否只需要较少分层的代码。

    【讨论】:

    • 谢谢,如果我对同一个字符串有多个偏移值怎么办?如何做到这一点?
    • 您的解决方案非常完美,但唯一的问题是,很难将输出更改为对象。像这样[{ 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' }]
    • @stacks:用另一个版本更新。任何进一步的更改都可能涉及一个新问题。
    • 我按照建议创建了一个新问题,stackoverflow.com/questions/55001801/…
    【解决方案2】:

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

    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)

    【讨论】:

    • 你不需要为text1打电话给text.substr(0, offset)吗?
    • 文字1错了,应该是这样的Do you have questions or comments and do you wish to contact ABC? Please visit our
    • 它当前打印的像 "text1": "Do you have questions or comments and do you wish to contact ABC? Please visit our customer support page." 这是错误的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-27
    • 1970-01-01
    • 2013-10-19
    • 1970-01-01
    • 2012-08-25
    • 1970-01-01
    相关资源
    最近更新 更多