[求助] 想了一天也没搞定,如何用 js 分割字符?

2022-02-11 05:54:03 +08:00
 iPc666

各位大牛,请教个问题。有个翻译 api 每次最多 1000 个字,现在有一段文本大约 5000 字,每行在 100 字左右,我想尽可能多的把这 5000 个字用行分割,但尽可能生成少的数组,从而尽可能少的循环请求翻译接口,请问如何实现呢?

想了一天没想到什么好方法,如何用 JS 实现呢?


a = `这是第一行
这是第二行
这是第三行

这是第 n 行
`

最终需要生成数组 b

b =['尽可能多但不超过 1000 个字,不能在每行中断开','同前一项']

3073 次点击
所在节点    JavaScript
20 条回复
Chad0000
2022-02-11 06:02:45 +08:00
如果你 JS 是负责前端,那么这种事情应该在后端处理,同时也方便后端随时切换到其他翻译 API 。
iPc666
2022-02-11 06:04:36 +08:00
@Chad0000 我要用 nodejs 处理
nifury
2022-02-11 06:12:34 +08:00
先按行分割,然后把相邻行合并直到没法再加新行(不然就>1000 字)

不是最优解,但近似吧……又不是算法题,好实现就行
Chad0000
2022-02-11 06:13:48 +08:00
@iPc666 #2 我跟 NodeJS 打交道的也就 Angular 了。后端我用 C#,你这个方案应该不麻烦吧,直接按行分成数组,再将数组分组调用,分组的方式为加起来不超过 1000 字。直接一个循环累加字符长度,直到超过 1000 就把之前的打包成一组进行翻译,然后从这里重新累计字符长度。

如果你还要计算最优解,尽量再减少数组,可能就需要考虑分析每组翻译“浪费”的字符数,甚至可以把数组打乱顺序以达到最少“浪费”,但这样过于折腾,能节省多少费用,以及是否会影响翻译,综合看来我觉得就没必要了。
iPc666
2022-02-11 06:31:31 +08:00
以每行分割成数组后,怎么通过一次循环实现呢?
musi
2022-02-11 07:06:37 +08:00
a = `这是第一行
这是第二行
这是第三行

这是第 n 行
`
const arr = a.split('\n');
const texts = [];
let str = ''
while(arr.length) {
const currentText = arr.shift()
// 限制每段文本的长度不超过 10
if(str.length + currentText.length <= 10){
str += currentText
}else{
texts.push(str);
str = currentText
}
}
texts.push(str);
str = ''
console.log(texts)


=> ['这是第一行这是第二行', '这是第三行', '这是第 n 行']
gzlock
2022-02-11 07:12:56 +08:00
不知道对题目理解的对不对
https://codepen.io/gzlock/pen/dyZWLZB
gzlock
2022-02-11 07:13:51 +08:00
@musi #6 有一说一,如果没有了换行符提交去翻译的话,翻译结果绝对有问题
musi
2022-02-11 07:22:28 +08:00
@gzlock 这得看原文本有没有标点符号吧,如果标点符号用的规范也不见得有多大问题
musi
2022-02-11 07:23:43 +08:00
@gzlock #7 如果原文本没有标点符号,那 op 的一行 100 字翻译也有问题,这就直接无解了。
iPc666
2022-02-11 07:25:26 +08:00
用这段代码搞定了
···
function splitStrIntoArray(str, maxLength) {
let i;
let output = [];
let lineSoFar = "";
let temp;
let line = str.split('\n');
for (i = 0; i < line.length;) {
temp = addLineOntoLineWrap(lineSoFar, line[i]);
if (temp.length > maxLength) {
if (lineSoFar.length === 0) {
lineSoFar = temp;
i++;
}
output.push(lineSoFar);
lineSoFar = "";
} else {
lineSoFar = temp;
i++;
}
}
if (lineSoFar.length > 0) {
output.push(lineSoFar);
}
return output;
}

function addLineOntoLineWrap(lineWrap, line) {
if (lineWrap.length !== 0) {
lineWrap += "\n";
}
return lineWrap + line;
}

b = splitStrIntoArray(a,1000)

···
madao1993
2022-02-11 07:33:30 +08:00
split 分割字符串,for 循环遍历数组元素,数组的 length 属性相加超过 1000 就 i--然后 continue
这不是最优解,但是很方便
iPc666
2022-02-11 07:36:18 +08:00
@gzlock 你的代码有问题,max 给 1000 , 控制台报错 https://codepen.io/youxiaohou/pen/KKymYbQ
gzlock
2022-02-11 07:41:30 +08:00
@iPc666 #13 报错处是你后加的代码吧,不背锅
iPc666
2022-02-11 08:24:18 +08:00
感谢大家,问题已解决。成品效果图 https://www.crxsoso.com/webstore/detail/fdpohaocaechififmbbbbbknoalclacl
jorneyr
2022-02-11 08:24:24 +08:00
String.substring(x, 1000),从这个位置向前找最近的一个换行符作为分割位置。
x 为上一次的分割位置。
z4none
2022-02-11 10:11:47 +08:00
各行可以乱序提交? 这就是个装箱问题.
mekingname
2022-02-11 10:34:29 +08:00
问题来了,如果有一个词跨行了怎么办?它翻译的时候肯定会出问题吧。
RickyC
2022-02-11 13:50:18 +08:00
这是智力题吗?
一段文字,翻译完不就行了。
干嘛追求解题效率最高呢?
iPc666
2022-02-11 21:37:26 +08:00
跨行了就是人工智能的范畴了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/833087

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX