考虑一个字符串,它的第一个字母总是"M",它的其他字符几乎可以是"I"s"U"s的任意组合(不允许使用其他字母,只要IsUs)例如:MIUMUIMIUIUMUIIUIUMUIIIUIIIUIIIMIUUIUIIIUUI"III"都是此类字符串。
我想要一个函数,给定任何这样的字符串作为输入,返回一个数组,其中包含模式"U"可以使用的所有可能方式,如果它出现在输入字符串中,则在输入中替换为"III"。例如,有两种方法可以用"U"替换"MIIII",即MUIMIU因此,给定MIIII作为输入,函数应该返回[MUI, MIU]
这是我的(有缺陷的)功能。其背后的思想是循环输入字符串(即MIstring)以查找"III"每次发现"III"时,MIstring都会添加到IIIoptions数组中,但"U"会替换"III"

function ruleThree() {
    var IIIoptions = [];
    for (var i = 0; i < MIstring.length; i++) {
        if (MIstring.slice(i, i+3) === "III") {
           IIIoptions.push(MIstring.replace(MIstring.slice(i, i+3), "U"));
        }
    }
    return IIIoptions;
}

给定输入MIIII,我希望函数返回[MUI, MIU]。但是,它返回[MUI, MUI]我尝试过使用不同的输入,但它显示了相同的问题,即数组中的所有项都是相同的例如,给定字符串MIIIIUIIIIU,它将给我[MUIUIIIIU, MUIUIIIIU, MUIUIIIIU, MUIUIIIIU],而不是[MUIUIIIIU, MIUUIIIIU, MIIIIUUIU, MIIIIUIUU]。所以这个函数得到了mistring right中包含的"III"s个数,但是它没有返回我希望它返回的数组。
我的功能怎么了?

最佳答案

主要的问题是您使用的是String.replace(),并且该方法将始终用您调用它的方式将第一个匹配的III序列替换为U当找到匹配项时,可以使用String.slice()生成带有替换项的新字符串,如下所示:

const input = "MIIIII";

function ruleThree(str)
{
    var IIIoptions = [];

    for (var i = 0; i < str.length; i++)
    {
        if (str.slice(i, i + 3) === "III")
           IIIoptions.push(str.slice(0, i) + "U" + str.slice(i + 3));
    }

    return IIIoptions;
}

console.log(ruleThree(input));

.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

但是,请注意,如果一次需要多个替换,则前面的方法将失败,例如,如果输入MIIIIII,则不会生成MUU字符串。在这种情况下,必须使用递归方式:
const input = "MIIIIIII";

function getCombs(str, res = new Set())
{
    for (var i = 0; i < str.length; i++)
    {
        if (str.slice(i, i + 3) === "III")
        {
           let r = str.slice(0, i) + "U" + str.slice(i + 3);
           res.add(r);
           getCombs(r, res);
        }
    }

    return [...res];
}

console.log(getCombs(input));

.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

10-07 13:02