如何迭代多行字符串值的分割结果数组以重新格式化某些行/换行符?

3

我有一串带有换行的数据。

例如:

"Product Name \n Product Color \n Product Quantity \n Product Location \n Product Size \n Product Power" 

字符串中的元素数量可能是无限的。

我需要将\n替换为>>>> \n,但仅当行号大于3且不是最后一行时才需要替换。在最后一行上,我需要它显示(end)

我已经尝试使用map进行分割和替换,但我无法遍历数组以识别要修改的行,也无法在所有行被修改或未被修改时将它们重新连接起来。

输入为:

"Retract-A-Banner\n**Template:\nFull Color\nImprint Information:\nCL: 488 Special Ops Wing\n353 SOW Integrated Resilience Optimization Network\n"

期望的输出:

"Retract-A-Banner\n**Template:\nFull Color >>>> \nImprint Information: >>>> \nCL: 488 Special Ops Wing >>>> \n353 SOW Integrated Resilience Optimization Network(end)\n"

3
输入是指计算机程序或系统接收的数据,输出是指计算机程序或系统处理后生成的结果。以下是示例:输入:
  • 一段文字
  • 一个数字
  • 一个图像
输出:
  • 经过处理后的文字
  • 运算后的数字
  • 处理后的图像
- epascarello
您是要查找一个字面上的“反斜杠+n”还是一个换行符? - skara9
这将是字面上的反斜杠和n,因为它将保持为字符串,评估代码的应用程序将处理实际的换行过程。连续的换行符将被相同地处理,直到结束。 - David Romstad
@DavidRomstad ... 关于提供的所有答案/解决方案/方法,还有什么问题吗? - Peter Seliger
@PeterSeliger 这些方法和解决方案已经被证明非常有帮助。回答的群体非常多样化,对不同方法有着很好的洞察力和实践经验。感谢所有的回答。然而,对于我的情况来说最简洁的答案是:通过 \n 进行分割并使用以下条件重新创建字符串:如果这是最后一个,则添加 (end) 如果行大于 3,则添加 >>>> \n 否则,只需一个简单的 \n 即可 编辑:添加一个检查,检查最后一个字符串是否为 \n,并从数组中删除该值。 - David Romstad
显示剩余4条评论
6个回答

2

通过\n进行分割,并根据以下条件重新创建字符串:

  1. 如果这是最后一个,则添加(end)
  2. 如果行大于3,则添加>>>> \n
  3. 否则,只需简单的\n即可

编辑:

添加一个检查,检查最后一个字符串是否为\n,并从数组中删除该值。

const str = "Retract-A-Banner\n**Template:\nFull Color\nImprint Information:\nCL: 488 Special Ops Wing\n353 SOW Integrated Resilience Optimization Network\n";

const splitted = str.split('\n');
let output = '';

if (splitted[splitted.length - 1] === '')
  splitted.length--;
  
for (let i = 0; i < splitted.length; i++) {
  if (i + 1 === splitted.length) {
    output += splitted[i] + ' (end)';
  } else if (i >= 2) {
    output += splitted[i] + ' >>>> \n';
  } else {
    output += splitted[i] + '\n';
  }
}

console.log(output);


需要决定最后一行的值如何连接结果。目前,由于最后一行是空字符串值'',所以当前结果与OP的期望值不相等。此外,在连接' >>>> \n'时也存在一行计数错误。 - Peter Seliger
1
只有一个小问题... 代码从 ... } else if (i >= 3) { ... 改为 ... } else if (i >= 2) { ... . - Peter Seliger

2
实际上,在.split(/\n/)操作的结果数组中,不一定需要选择迭代方法。
相反,下一个介绍的方法通过直接访问数据(获取所有所需信息)来工作... 并且根据最后一行的值在现场组装返回值...

function parseNewlines(value) {

  const[ line1, line2, ...rest ] = String(value).split(/\n/);
  const lastLine = rest.pop();

  return [
    `${ line1 }\n${ line2 }\n${ rest.join(' >>>> \n') }`,

    (lastLine === '')
      && `(end)\n`
      || ` >>>> \n${ lastLine }(end)`,

  ].join('');
}

const originalTestValue = `Retract-A-Banner
**Template:
Full Color
Imprint Information:
CL: 488 Special Ops Wing
353 SOW Integrated Resilience Optimization Network
` // be aware of the last line.

const alteredTestValue = `Retract-A-Banner
**Template:
Full Color
Imprint Information:
CL: 488 Special Ops Wing
353 SOW Integrated Resilience Optimization Network` // be aware of the last line.

// be aware of the last line.
const expectedResult = `Retract-A-Banner\n**Template:\nFull Color >>>> \nImprint Information: >>>> \nCL: 488 Special Ops Wing >>>> \n353 SOW Integrated Resilience Optimization Network(end)\n`;

// be aware of the last line.
const expectedResultOfAlteredValue = `Retract-A-Banner\n**Template:\nFull Color >>>> \nImprint Information: >>>> \nCL: 488 Special Ops Wing >>>> \n353 SOW Integrated Resilience Optimization Network(end)`;

console.log(
  `OP's use case ...\n${ parseNewlines(originalTestValue) }`
);
console.log(
  `altered use case ...\n${ parseNewlines(alteredTestValue) }`
);
console.log('\n');

console.log(
  "OP's use case ...\ntest passed ?..",
  (parseNewlines(originalTestValue) === expectedResult)
);
console.log('\n');

console.log(
  "altered use case ...\ntest passed ?..",
  (parseNewlines(alteredTestValue) === expectedResult)
);
console.log(
  "altered use case and altered expectation ...\ntest passed ?..",
  (parseNewlines(alteredTestValue) === expectedResultOfAlteredValue)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

然而,可以使用经典的reduce任务来实现迭代方法。

function parseNewlines(value) {
  return String(value)

    .split(/\n/)
    .reduce((result, line, idx, arr) => {
      return [

        result,
        (idx < (arr.length - 1))

          ? `${ (idx >= 3) && ' >>>> ' || '' }\n${ line }`
          : (line === '')
              && `(end)\n`
              || ` >>>> \n${ line }(end)`,

      ].join('');
    });
}

const originalTestValue = `Retract-A-Banner
**Template:
Full Color
Imprint Information:
CL: 488 Special Ops Wing
353 SOW Integrated Resilience Optimization Network
` // be aware of the last line.

const alteredTestValue = `Retract-A-Banner
**Template:
Full Color
Imprint Information:
CL: 488 Special Ops Wing
353 SOW Integrated Resilience Optimization Network` // be aware of the last line.

// be aware of the last line.
const expectedResult = `Retract-A-Banner\n**Template:\nFull Color >>>> \nImprint Information: >>>> \nCL: 488 Special Ops Wing >>>> \n353 SOW Integrated Resilience Optimization Network(end)\n`;

// be aware of the last line.
const expectedResultOfAlteredValue = `Retract-A-Banner\n**Template:\nFull Color >>>> \nImprint Information: >>>> \nCL: 488 Special Ops Wing >>>> \n353 SOW Integrated Resilience Optimization Network(end)`;

console.log(
  `OP's use case ...\n${ parseNewlines(originalTestValue) }`
);
console.log(
  `altered use case ...\n${ parseNewlines(alteredTestValue) }`
);
console.log('\n');

console.log(
  "OP's use case ...\ntest passed ?..",
  (parseNewlines(originalTestValue) === expectedResult)
);
console.log('\n');

console.log(
  "altered use case ...\ntest passed ?..",
  (parseNewlines(alteredTestValue) === expectedResult)
);
console.log(
  "altered use case and altered expectation ...\ntest passed ?..",
  (parseNewlines(alteredTestValue) === expectedResultOfAlteredValue)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }


不错的方法!只是有一个注意点,我们现在可以使用 lastLine = rest.at(-1) 来替代 lastLine = rest.pop() - A1exandr Belan
@AlexandrBelan ... pop 很必要,因为我们不仅需要访问/分配 lastLine,还需要修改/改变 rest 数组。 - Peter Seliger
1
哦,我明白了。谢谢! - A1exandr Belan

1
如何尝试这样的方案:
var data =
  "Retract-A-Banner\n**Template:\nFull Color\nImprint Information:\nCL: 488 Special Ops Wing\n353 SOW Integrated Resilience Optimization Network\n";

function convertToLines(entry) {
  return entry.split("\n").filter((val) => val);
}

function constructOutput(lines) {
  const numLines = lines.length;
  return lines.reduce((result, entry, index) => {
    var separator = index > 2 ? " >>>> \n" : "\n";
    if (index == numLines - 1) {
      separator = "(end)\n";
    }
    return result + entry + separator;
  }, "");
}
console.log(constructOutput(convertToLines(data)));

convertToLines使用filter来删除由字符串末尾的换行符引起的空条目。然后我们必须将其附加到(end)分隔符上。


这非常有帮助,谢谢! - David Romstad
@mrrogers...你测试了上面的解决方案吗?实现中在前三行后进行换行符替换时出现了一行计数错误(这里是在第四行之后)。 - Peter Seliger
我刚刚进行了一个视觉测试,认为我已经正确地排好了东西的位置。此外,我可能过于深入地阅读了通过使用“filter”删除空行的解决方案。所以,我想这个解决方案接近完美,但可能还需要调整一下,以解决结束/空行条件。 - mr rogers

1
  • Convert string into an array of strings

     string.split(/\n/)
    
  • Then use .flatMap() and a chained ternary as callback. Each condition is based on index

      idx < 3 ? [str+' \n']
      :
      idx === arr.length -1 ? [str+' (end)'] 
      : 
      [str+' >>>> \n']
    
  • Then .join('') the array back into a string

let test = `Retract-A-Banner\nTemplate:\nFull Color\nImprint Information:\nCL: 488 Special Ops Wing\n353 SOW Integrated Resilience Optimization Network\n" Expected Output:"Retract-A-Banner\nTemplate:\nFull Color \nImprint Information: \nCL: 488 Special Ops Wing \n353 SOW Integrated Resilience Optimization Network`;

const formatLines = string => string.split(/\n/).flatMap((str, idx, arr) => idx < 3 ? [str + ' \n '] : idx === arr.length - 1 ? [str + ' (end) '] : [str + ' >>>> \n ']).join('');

console.log(formatLines(test));


0

看起来你想要这样的东西:

var strings = `Retract-A-Banner\nTemplate:\nFull Color\nImprint Information:\nCL: 488 Special Ops Wing\n353 SOW Integrated Resilience Optimization Network\n`.split("\n");
strings.forEach((string,index) => {
    if (index > 2) {
       strings[index] = `>>>>\\n${string}`
    } else {
       index > 0 ? `\\n${string}` : strings[index];
    }
})
var finalString = strings.join("")+"(end)";
console.log(finalString);

请注意,我在代码中使用了额外的反斜杠来转义您的\n。不过我无法确定这是否符合您的要求。

这就是问题所在,我无论如何都无法获取索引值。但唯一的问题是它会在字符串开头添加一个 \n。我需要避免这种情况发生。 - David Romstad
你是指第一个字符串吗?我已经更新了它以消除这个问题。 - Marc
这是一个很好的开始,谢谢,这非常有帮助。 - David Romstad
@Marc...你测试过上述解决方案了吗?结果与OP期望的值不相等。 - Peter Seliger

0

要插入 >>>>,您可以使用正则表达式:(?<=(.+\n.+){2,})(?=\n.)

  • (?<=(.+\n.+){2,}) 创建了一个三行的正向回顾
  • (?=\n.) 创建了一个换行符后跟任何字符的正向前瞻

然后,您可以使用类似的正则表达式 (?<=.)(?=\n*$)'(end)' 添加到最后一行。

const input = "Retract-A-Banner\n**Template:\nFull Color\nImprint Information:\nCL: 488 Special Ops Wing\n353 SOW Integrated Resilience Optimization Network\n";

const output = input
                .replace(/(?<=(.+\n.+){2,})(?=\n.)/g, ' >>>> ')
                .replace(/(?<=.)(?=\n*$)/, '(end)');

console.log(input);
console.log(output);


如果您在字符串中使用了反斜杠后跟着一个 'n',那么它将被格式化为 \\\n 在您的 JS 字符串文字中。

在这种情况下,您可以使用正则表达式 (?<=(.+\\n.+){2,})(?=\\n.) 来插入 >>>> 和正则表达式 (?=\\n$) 用于 (end)

const input = "Retract-A-Banner\\n**Template:\\nFull Color\\nImprint Information:\\nCL: 488 Special Ops Wing\\n353 SOW Integrated Resilience Optimization Network\\n";

const output = input
                .replace(/(?<=(.+\\n.+){2,})(?=\\n.)/g, ' >>>> ')
                .replace(/(?=\\n$)/, '(end)');

console.log(input);
console.log(output);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接