2017-07-12 74 views
1

我正试图解决Codewars上的What's up next?挑战。挑战有一系列值作为第一个输入,顺序中的一个项目作为第二个输入,并且需要您按照指定项目的顺序返回项目。给出的实施例 -JavaScript:了解使用生成器和生成的序列

nextItem([1, 2, 3, 4, 5, 6, 7], 3) # 4 
nextItem("testing", "t") # "e" 

有一种使用发电机来产生的值作为第一个参数的序列的样品测试的情况下,而这正是我难倒 -

function* countFrom(n) { for (let i = n; ; ++i) yield i; } 
Test.assertEquals(nextItem(countFrom(1), 12), 13); 

我不知道我是否了解这台发电机的工作原理。综观测试时,我最初以为发电机产生的1序列至12,然后只需12后的数量必须返回,即13

此基础上,我的代码是 -

function nextItem(xs, item) { 
    // TODO: Implement me 
    // if sequence is a string, like "testing" 
    if (typeof xs === "string") { 
    xs = arguments[0].split(''); 
    } 

    // if sequence is an array(not a generator sequence) 
    if(Array.isArray(xs)) { 
    if(!xs.includes(item) || xs.lastIndexOf(item) === xs.length -1) { 
     return undefined; 
    } 
    return xs[xs.indexOf(item)+1]; 
    } 
    else { 
    // if seqeunce is from a generator 
    let temp = []; 
    for(let i = xs.next().value; i <= arguments[1]; i++) { 
     temp.push(i); 
    } 
    xs = temp; 
    return xs[xs.length-1] + 1; 
    } 

} 

这失败约一半的测试案例 -

Time: 326ms Passed: 9 Failed: 9 
Test Results: 
Test Passed: Value == 4 
Test Passed: Value == undefined 
Test Passed: Value == undefined 
Test Passed: Value == 'e' 
Test Passed: Value == '!' 
Test Passed: Value == undefined 
Test Passed: Value == undefined 
Test Passed: Value == 701 
Expected: undefined, instead got: 661 
Test Passed: Value == 661 
Expected: 664, instead got: 661 
Expected: undefined, instead got: 661 
Expected: undefined, instead got: 661 
Expected: 664, instead got: 661 
Expected: 662, instead got: 661 
Expected: undefined, instead got: 661 
Expected: undefined, instead got: 661 
Expected: 662, instead got: 661 

我敢肯定,我这里的发电机如何使用是有缺陷的认识。在这一行 - nextItem(countFrom(1), 12)中,我不认为生成的序列是1到12.我能说的是它会生成“some”序列,当您将12传递给函数时,它会返回序列中的下一个项目 - 13。

我确实在发电机上经过了这个article,但不知道如何在这里应用它。

希望能够解释如何解决这一难题。

回答

2

我明白这台发电机的工作原理。看看测试用例,我最初认为发生器产生1至12的序列。

不,发生器产生无限序列。注意循环没有条件,只要您在迭代器上调用next(),它就会一直运行,并向下一个yield迈进。

对于如何解决这一难题,我将不胜感激。

重点是字符串,数组和发生器都是iterable。你不应该区分它们,并为每个案例写一个不同的案例。你只应该使用通用[Symbol.iterator]()接口,并提前通过:

function nextItem(xs, item) { 
    const iterator = xs[Symbol.iterator](); 
    var value = NaN, // bad trick: a value known not to ===item 
     done = false; 
    while (!done && value !== item) 
    ({value, done} = iterator.next()); 
    return iterator.next().value; 
} 

或者更容易,不关心这一点,只需使用for of循环:

function nextItem(xs, item) { 
    var found = false; 
    for (const x of xs) { 
    if (found) return x; 
    found = x === item; // whether to be returned in the next iteration 
    } 
} 
+0

在第一个例子中,' while(value === item)break;'也可以交换'(迭代器的常量值);'因为迭代器也是可迭代的。 – loganfsmyth

+0

@loganfsmyth很好,没有想到这一点,它可以让我们避免第二个例子中的'found'标志。在第一个片段中,我想明确地使用'.next()'然而 – Bergi

+0

@Bergi感谢一堆!今天学到了一件新事物,非常有用。 –