我有一个字符串数组,它们要么是一个星号("*"
),要么是其他字符。
我想“合并”连续的星号如下:
如果一行中有一个或多个星号,则将它们从数组中删除,并在下一个非星号元素前添加一个 * 单个 * 星号。如果星号位于数组的末尾,则只需删除它们。
一些较小的例子:
[..., "*", "4", ...] => [..., "*4", ...] // concat asterisk with string at the right
[..., "*", "*", "4", ...] => [..., "*4", ...] // remove first asterisk
[..., "*", "4", "*"] => [..., "*4"] // remove last asterisk
[..., "4", "*", "*", "*"] => [..., "4" ] // remove all asterisk which have no alphanumeric at its right
对于此全尺寸输入:
let data = ["0", "1", "2", "3", "4", "5", "6", "*", "*", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "*", "34", "*", "36", "37", "*", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "*", "54", "*", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "*", "*", "*", "*", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "*", "91", "92", "93", "94", "95", "*", "97", "*", "*"];
结果应为:
["0", "1", "2", "3", "4", "5", "6", "*9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "*34", "*36", "37", "*39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "*54", "*56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "*78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "*91", "92", "93", "94", "95", "*97"]
如何实现这一点?以下是我的尝试:
let data = ["0", "1", "2", "3", "4", "5", "6", "*", "*", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "*", "34", "*", "36", "37", "*", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "*", "54", "*", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "*", "*", "*", "*", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "*", "91", "92", "93", "94", "95", "*", "97", "*", "*"];
let output = data.map((d, index, arr) => arr[index - 1] === '*' ? '*'+d : d).filter(d => d !== '*');
console.log(output);
7条答案
按热度按时间ehxuflar1#
您可以在一个循环中完成此操作,只需检查当前元素是否为
*
,如果不是,则为push()
,如果前一个元素为*
,则连接。如果您愿意,也可以在
reduce()
调用中使用相同的逻辑或者,您可以通过在每次迭代时存储前一个值来避免串联中的第二个条件(以及第二次数组访问)。这类似于函数中的状态机答案,但避免了重复的解构和对象创建。
基本在线基准测试
| 测试用例名称|结果|
| --------------|--------------|
| 简单循环(存储上一页)|1,228,712次操作/秒±2.22%(采样64次运行)|
| 简单回路|351,955次操作/秒±0.24%(采样67次运行)|
| 状态机|31,174次操作/秒±0.27%(采样64次运行)|
iyfamqjs2#
这可以建模为一个简单的状态机:
我们从一个空的状态值开始。当状态为空并且遇到星号时,我们移动到星号状态。当我们遇到不同的值时,我们将其附加到我们的输出并保持在空状态。当我们处于星号状态时,如果我们遇到星号,我们保持在星号状态并不处理输出。当我们遇到其他东西时,我们将
*<value>
附加到输出中,并返回到空状态。最后不需要清理;我们只返回输出。我们可以用一个简单的
reduce
调用来编写这个状态机,它跟踪一个state
变量和当前的output
数组,如下所示:因为我们的状态值要么是一个星号,要么是一个空字符串,所以我们可以将它放在值的前面,然后将结果追加到输出数组中。
lvmkulzt3#
说明-
1.循环元素。
1.检查当前项和下一项的顺序,如果是
*<non_star>
,则合并两者并将其推入新数组。1.如果当前项目不是一个星星,也不是已经作为
*<curent_item>
出现,那么也推它。pgvzfuti4#
下面是皮尔彻的“简单循环(store prev)”解决方案的优化版本:
区别在于:
prev
中存储布尔值而不是字符串prev
该基准给出:
| 测试用例名称|结果|
| --------------|--------------|
| 折叠Prev|1,130,945次操作/秒±0.59%(采样65次运行)|
| 折叠Prev 2|1,299,316次操作/秒±0.73%(采样67次运行)|
pw9qyyiw5#
您几乎就完成了!缺少的一个功能是测试连续的
*
s?qltillow6#
至于OP的用例,我提出了一个数组
join
,基于regex的字符串replace
和字符串split
方法,其中正则表达式模式如下......以及它的description is provided with the pattern's test/playground page。
其优点是将提供的数组数据作为一个大字符串处理(因此
join
处理数组),并使用单个基于正则表达式的replace
任务处理它,其中中间替换结果是split
再次进入最终数组结构。编辑...以便提供一种***“更贴近实际”***的方法。
***最后一点***我自己发现基于正则表达式的变体更优雅,更有表现力,尽管上面提供的解决方案可能更容易阅读/维护初学者。
p3rjfoxz7#
这里有一个解决方案。