javascript 为什么要在if语句中使用[i + j]和j+1?

rbl8hiat  于 2023-03-11  发布在  Java
关注(0)|答案(2)|浏览(126)

我正在尝试理解代码解决方案来查找字符串中第一个出现的索引问题。我在网上找到了这段代码,但我可以很好地把我的头包在两个ifs语句行:
如果(针[j]!==干草堆[i + j])断裂;
如果(j + 1 ===针长)
有人能把它分解一下吗?

let strStr = (haystack, needle) => {
    // we loop through the first string 
    for (let i = 0; i < haystack.length; i++) {
        // we loop through the second string
        for (let j = 0; j < needle.length; j++) {
            if (needle[j] !== haystack[i + j]) break;
            if (j + 1 === needle.length) {
                return i
            }
        }
    }
    return -1
};
strStr('sadbutsad', 'sad')
qnakjoqk

qnakjoqk1#

为了理解代码的作用,首先需要理解break语句:break将退出 closest/nearest 循环,即缩进最多的循环:

for (let a ...) { // for A
    for (let b ...) {  // for B
        break; // this will break for B
    }
    // after the break, the code execution will resume here
    console.log("more code here...")
}

现在,对于您的代码,2个for语句逐个字符地迭代2个字符串:haystackneedle。让我们给予这些字符串一些值,以便更好地解释:

  • haystack =“你好,世界!!!”
  • 指针=“世界”

第一个for(使用变量i)逐字符遍历 haystack,对于每个索引i,它尝试将 needle 字符串与 haystack 字符串的某个部分进行匹配,从索引i开始:

  • i = 0:
0123456789... (haystack indices)
haystack: hello world!!!
          ^i=0

needle:   world
          01234  (needle indices)
  • i = 1:
0123456789... (haystack indices)
haystack: hello world!!!
           ^i=1

needle:    world
           01234  (needle indices)
  • i = 2:
0123456789... (haystack indices)
haystack: hello world!!!
            ^i=2

needle:     world
            01234  (needle indices)
  • 等等......直到i = 6:
0123456789... (haystack indices)
haystack: hello world!!!
                ^i=6

needle:         world
                01234  (needle indices)

第二个for实际上是逐个字符地比较字符串中对齐的部分是否相等,这次是逐个字符地比较 needle 字符串,首先,我们需要比较 haystack 中索引为6的字符(“w”)和 needle 中索引为0的字符(也是“w”):

0123456789... (haystack indices)
haystack: hello world!!!
                ^i=6

needle:         world
                01234  (needle indices)
                ^j=0

如果这个相等失败,我们停止整个比较(这是第二次,使用j变量,使用break语句),接下来,我们在j=1时再次这样做:

0123456789... (haystack indices)
haystack: hello world!!!
                ^i=6

needle:         world
                01234  (needle indices)
                 ^j=1

现在,我们需要对比两个(分别在2个字符串中的索引71处)。为了得到7,我们添加i + j,并且为了得到1,我们仅使用j。最后,如果我们检查所有字符并且它们都匹配,我们要报告“成功”(我们通过返回 haystack 中的索引i来实现,在该索引处我们匹配了 needle)如果到达最后一个字符,我们知道我们完成了对所有字符的检查,即needle.length - 1(因为长度5意味着索引0-4;last index is 4 = 5-1).这是if检查的内容--是否到达最后一个字符.如果到达,则意味着break语句从未执行过,因此没有一个字符不匹配.

jchrr9hc

jchrr9hc2#

所以这段代码实际上 * 做的 * 是查看字符串haystack,并返回haystack中的子字符串needle的开头的字符索引,如果有的话。
if (needle[j] !== haystack[i + j]) break;在上下文中,i是haystack的子字符串的开始,当前正在测试它是否与needle相同。内部循环j检查needle和haystack的每个字符,以查看它们是否相同。“needle”总是从零开始,因为您正在查看整个字符串,所以你使用needle[j]。“haystack”从i开始,因为有外循环,所以它使用haystack[i+j]。如果这些字符不匹配,那么你的内循环知道它找到了和needle不同的东西,所以中断并继续外循环的下一次迭代。
if (j + 1 === needle.length) return i更容易解释:如果needle有三个字符长,那么只需要检查三个字符,由于它们都匹配(我们知道这一点是因为前面的条件没有break),那么我们就知道我们已经在干草堆中找到了needle,并且可以返回它的初始索引。
(This严格地说,是不必要的,因为内部循环I无论如何都要在那个点结束(因为j只迭代到needle.length),所以不用if语句,你可以在内部循环之后简单地使用return i:如果你到达那个点而没有突破,你就知道你有一场完整比赛。
我怀疑包含这一行只是为了让它更明确,并且在教学环境中更容易理解代码。就我个人而言,有时候我会故意包含这样的“不必要”代码,如果它让函数更容易理解的话,尽管在这种情况下,代码注解也会起作用。

let strStr = (haystack, needle) => {
    // we loop through the first string 
    for (let i = 0; i < haystack.length; i++) {
        // we loop through the second string
        for (let j = 0; j < needle.length; j++) {
            // if the "j"th character of needle is not the same as the "j"th character of haystack starting at i:
            if (needle[j] !== haystack[i + j]) break;
            
            // have we run out of needle to test?
            if (j + 1 === needle.length) {
                return i
            }
        }
        // (or we could just `return i` here instead of the "have we run out of needle" conditional above)
    }
    // if we made it here, we got all the way through the haystack without finding a needle, so indicate failure:
    return -1
};
console.log(strStr('sadbutsad', 'sad'))

你给出的例子的结果是0,但是如果不是简单的例子,解释一下会更好一些,比如“haystack”包含“xyzababcdxyz”,“needle”是“abcd”。
i将从0开始,j将从0开始,needle[j]是“a”,并且haystack[i+j]是“x”。它们不相等,因此将中断;对于i=1和i=2也是如此。
i=3上,事情变得更加有趣。
内部循环再次从零开始。needle[j]needle[0]是“a”。haystack[i+j]haystack[3+0]是“a”。这匹配,所以我们继续i=3,j=1,并得到needle[1]haystack[4],它们再次匹配(“B”)。所以我们继续i=3,j=2,这是needle[2]haystack[5]的比较,但是它们不匹配(“c”和“a”)。所以我们再次跳出内部循环,再次递增i
i=4,j=0不匹配,所以我们立即中断。
在i=5时,我们又开始看到匹配,这一次,遍历needle的整个长度,没有发现不匹配,所以我们知道可以返回i作为输出。

相关问题