简体   繁体   English

Javascript 发生器 function 好像没有调用

[英]Javascript generator function does not seem to be called

I have written the following Javascript function.我写了以下 Javascript function。 It is supposed to return all the unique permutations (including partial permutations) of the elements of the input array;它应该返回输入数组元素的所有唯一排列(包括部分排列); it is coded as a generator (introduced by function* and returning values using yield ), so that the values are evaluated lazily on demand.它被编码为生成器(由function*引入并使用yield返回值),以便根据需要延迟评估值。

function* permute(arr) {
    if (arr.length == 1)
        yield arr
    else if (arr.length) {
        for (let i of arr) {
            const value = arr[i]
            if (arr.indexOf(value) == i) {
                yield [value]
                const others = arr.slice(0, i).concat(arr.slice(i+1))
                for (let perm of permute(others))
                    yield [value, ...perm]
            }
        }
    }
}

To test it, I used the following Jest unit test:为了测试它,我使用了以下 Jest 单元测试:

describe("Permute tests", () => {
    test("No duplicates", () => {
        const input = "abc".split("")
        const expected = "a ab abc ac acb b ba bac bc bca c ca cab cb cba"
            .split(" ")
        for (let x of permute(input))
            expect(x.join("")).toBe(expected.shift())
        expect(expected.length).toBe(0)
    })
})

But when I run this, it doesn't give the expected results.但是当我运行它时,它并没有给出预期的结果。 The test fails at the last line because expected.length is not zero, it is 15 as no results from the generator have been processed.测试在最后一行失败,因为expected.length不为零,它是 15,因为没有处理来自生成器的结果。 And this is borne out by the fact that if I put a breakpoint on the first statement in the generator function, it is not hit;事实证明,如果我在生成器 function 的第一条语句上设置断点,它就不会被命中; it seems that next() is never called on the generator.似乎从未在生成器上调用 next() 。

I have written other generators, and successfully tested them, but this one consistently doesn't work.我已经编写了其他生成器,并成功测试了它们,但是这个始终不起作用。 What am I doing wrong?我究竟做错了什么?

Environment: NodeJS 14.16.0 and npm 7.10.0 on Windows 10 (or Ubuntu 20.04);环境:Windows 10(或 Ubuntu 20.04)上的 NodeJS 14.16.0 和 npm 7.10.0; Jest 26.6.3.开玩笑 26.6.3。

Your code seems to have some issue.您的代码似乎有一些问题。 it doesn't call recursively.它不会递归调用。 you can check this link Recursive Generators in JavaScript您可以在 JavaScript 中查看此链接 Recursive Generators

I tried below one it produces with same logic unique characters我尝试了下面一个它产生的具有相同逻辑唯一字符的

function* permute(arr) {
    if (arr.length == 1)
        yield arr
    else if (arr.length) {      
        for (i=0; i<arr.length; i++) {          
            const value = arr[i]            
            if (arr.indexOf(value) == i) {              
                //yield [value]                
                const others = arr.slice(0, i).concat(arr.slice(i+1))                     
                for (let perm of permute(others))                   
                    yield [value, ...perm]
            }
        }
    }
}
const p = permute("abc".split(""));
console.log(p.next().value)

Thanks to those who have contributed answers;感谢那些提供答案的人; my code is now working.我的代码现在可以工作了。 There were two problems, both relating to the way I was iterating over the array.有两个问题,都与我遍历数组的方式有关。

  • The first problem was that I was saying for (let i of arr) , which iterates over the values, not the indices;第一个问题是我说的是for (let i of arr) ,它迭代的是值,而不是索引; and I was then trying to use i to index into arr .然后我试图用i来索引arr

  • The second problem was that I changed it to for (let i in arr) , which iterates over the indices, but treats them as strings, not numbers .第二个问题是我将其更改为for (let i in arr) ,它迭代索引,但将它们视为字符串,而不是数字 Therefore, in the line const others = arr.slice(0, i).concat(arr.slice(i+1)) , the expression i+1 didn't return a number that is one more than i , but a number that is the result of concatenating i and 1: that is, the equivalent of saying i*10+1 .因此,在const others = arr.slice(0, i).concat(arr.slice(i+1))行中,表达式i+1没有返回比i大一的数字,而是一个数字这是连接i和 1 的结果:也就是说,相当于说i*10+1 In order to overcome this, I can either use a conventional for loop instead of a for...in loop, or change the expression i+1 to i*1+1 .为了克服这个问题,我可以使用传统for循环而不是for...in循环,或者将表达式i+1更改为i*1+1 I think I prefer the former.我想我更喜欢前者。

The amended version of the function, which works fine, is:工作正常的 function 的修订版是:

function* permute(arr) {
    if (arr.length == 1)
        yield arr
    else if (arr.length) {
        for (let i = 0; i < arr.length; i++) {
            const value = arr[i]
            if (arr.indexOf(value) == i) {
                yield [value]
                const others = arr.slice(0, i).concat(arr.slice(i+1))
                for (const perm of permute(others))
                    yield [value, ...perm]
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM