You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将句子数组按最大长度合并为完整句子块?递归是否最优?

按最大长度合并完整句子数组的实现方案

我们已经将长字符串通过正则拆分为由完整句子组成的数组,已知单个句子长度不超过设定的maxLength。需要将数组中的句子以空格连接,合并为若干长度不超过maxLength的字符串块,且每个块必须包含完整句子(支持...、?!等特殊句子结尾)。下面给出具体实现方案,并讨论递归是否为最优雅的实现方式。

输入与预期输出示例

// 输入字符串与拆分代码
const input = "This is the first sentence... This is the second, much longer sentence, with some additional puntuations?! Third sentence with a different length! Just a sentence ending with a number 980. Last but not least, the fourth sentence.";
const arr = input.replace(/([.?!])\s*(?=[a-zA-Z0-9])/g, "$1|").split("|");
const maxLength = 105;

// 期望输出数组
[
  "This is the first sentence... This is the second, much longer sentence, with some additional puntuations?!",
  "Third sentence with a different length! Just a sentence ending with a number 980.",
  "Last but not least, the fourth sentence."
]

一、使用Array.reduce()迭代实现

这是最直观的实现方式,通过遍历句子数组逐步构建符合要求的块:

function mergeSentences(sentences, maxLength) {
  return sentences.reduce((chunks, sentence) => {
    // 初始化第一个块
    if (chunks.length === 0) {
      return [sentence];
    }

    const lastChunk = chunks[chunks.length - 1];
    // 计算合并后的总长度(含空格)
    const combinedLength = lastChunk.length + 1 + sentence.length;

    if (combinedLength <= maxLength) {
      // 符合长度限制则合并到最后一个块
      chunks[chunks.length - 1] = `${lastChunk} ${sentence}`;
    } else {
      // 超出限制则新增一个块
      chunks.push(sentence);
    }

    return chunks;
  }, []);
}

// 调用示例
const result = mergeSentences(arr, maxLength);
console.log(result);

逻辑说明:

  • 以空数组作为初始结果容器
  • 遍历每个句子时,检查与最后一个块合并后的长度是否合规
  • 合规则合并,不合规则新增块,全程保持块内都是完整句子

二、使用递归实现

递归通过分治思想处理,每次处理当前句子与剩余句子的组合:

function mergeSentencesRecursive(sentences, maxLength, chunks = []) {
  // 终止条件:无剩余句子时返回结果
  if (sentences.length === 0) {
    return chunks;
  }

  const [current, ...rest] = sentences;
  const lastChunk = chunks[chunks.length - 1];

  if (!lastChunk) {
    // 无已存在块时,添加当前句子后递归处理剩余
    return mergeSentencesRecursive(rest, maxLength, [...chunks, current]);
  }

  const combinedLength = lastChunk.length + 1 + current.length;
  if (combinedLength <= maxLength) {
    // 合并到最后一个块后递归
    const updatedChunks = [...chunks.slice(0, -1), `${lastChunk} ${current}`];
    return mergeSentencesRecursive(rest, maxLength, updatedChunks);
  } else {
    // 新增块后递归
    return mergeSentencesRecursive(rest, maxLength, [...chunks, current]);
  }
}

// 调用示例
const resultRecursive = mergeSentencesRecursive(arr, maxLength);
console.log(resultRecursive);

逻辑说明:

  • 每次取出数组首个句子,判断能否与最后一个块合并
  • 根据判断结果更新块数组,递归处理剩余句子
  • 句子数组为空时返回最终块数组

三、哪种方式更优雅?

  • reduce迭代方案:代码简洁直观,符合常规阅读习惯,无递归栈溢出风险(适配超长数组),性能稳定,是日常开发的首选。
  • 递归方案:逻辑上符合分治思维,但对超长数组可能触发栈溢出,可读性不如迭代方案,仅在特定递归场景下有使用价值。

综上,递归并非最优雅的实现方式,Array.reduce()的迭代方案在可读性、性能和安全性上更优。

内容的提问来源于stack exchange,提问作者Sander Schnydrig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 05:05:25