文本行去重:别让trim悄悄改变数据

举报
yd_214130845 发表于 2026/10/17 10:00:23 2026/10/17
【摘要】 用一段实际通过六组测试的JavaScript参考实现,说明文本行去重中的空行、首尾空格、换行形式、Unicode序列和重复统计边界,避免trim悄悄改变原始数据。

从一个小工具确定规则

今天做文本行去重助手时,我先写了一个独立的参考函数,并在本机 Node.js 中运行了六组用例。这个工具的范围很小:按行去重、保留首次出现的顺序、统计结果。本文给出实际测试过的核心代码,重点讨论“什么算同一行”。

为什么不直接trim

把每行先trim再放进Set,确实能合并很多看起来相似的内容,但也会把 a、前面有空格的 a、后面有空格的 a 合成同一条。处理标识符清单、文本样例或格式敏感的片段时,这可能改变原始数据。我的默认规则是精确字符串比较,只统一换行,不改普通行中的字符。空白字符组成的行也不自动等同于空字符串。

已运行的参考实现

function dedupeLines(text, ignoreEmpty = true) {
  const lines = text === '' ? [] : text.replace(/\r\n?/g, '\n').split('\n');
  const seen = new Set();
  let empty = 0, removed = 0;
  for (const line of lines) {
    if (ignoreEmpty && line === '') { empty++; continue; }
    if (seen.has(line)) { removed++; continue; }
    seen.add(line);
  }
  return { input: lines.length, empty, removed, lines: [...seen] };
}

输入为空字符串时计为零行;其他输入先将CRLF和单独的CR统一成LF,再切分。因此,末尾换行会产生一个空行。默认过滤空字符串行,也允许调用者保留。两种模式都应明确,而不能靠隐含trim决定。

Set负责记录已出现的字符串,并按首次插入顺序迭代。这里既没有排序,也没有大小写折叠,因而 b、a、b 的结果仍是 b、a。

六组测试的实际结果

本机执行结果为6/6通过。测试对象就是上面的函数,断言覆盖以下情况:

用例 观察结果
b、a、b 保留b、a的首次顺序
混合CRLF、CR、LF 统一切行后正确去重
a、空行、a、末尾换行 默认输入4行、过滤2行、删除重复1行、保留1行
a与首尾带空格的变体 三条分别保留
中文及两种é写法 重复中文合并;不同Unicode序列保留
相同HTML片段出现两次 返回一条原始字符串

关闭空行过滤后,上述四行输入会保留 a 和一个空字符串,重复删除数为2。完全空输入仍为零行。

不把过滤数当成重复数

默认模式中,输入4行减去保留1行得到3,这个3包含两条空行,不能全部叫“重复删除”。因此函数分别返回empty和removed,便于界面分别展示。可核对的关系是:输入行数等于过滤空行数、重复删除数与保留行数之和。

字符相似和字符串相等是两件事

外观相同的é可能来自单个字符,也可能由e和组合重音构成。当前函数不自动normalize,因此它们分别保留。若业务希望合并,应单独设计归一化选项,并说明它会改变相等规则,而不是悄悄加到去重步骤中。

HTML用例只证明函数返回文本。浏览器展示时还要把结果写入textarea.value或textContent,不能为了展示方便直接赋给innerHTML。纯文本转换和DOM渲染属于不同环节,应分别检查。

使用边界与参考

这是适合小型清单的内存实现,没有做大文件流式处理,也没有进行大规模性能测试。输入、切分数组和集合都会占用内存;用于大文件时,应另行评估读取方式和大小限制。

语言行为参考:MDN的Set描述与String.prototype.normalize()文档。以下为参考地址:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Set
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。