我正在尝试解决Codewars上的What's up next?挑战。挑战有一系列值作为第一个输入,序列中的项目作为第二个输入,并且需要您在紧跟指定项目后的序列中返回该项目。举个例子 -
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.我可以告诉它生成“某些”序列,当你将12传递给函数时,它会返回下一个项目。序列 - 13.
我确实在生成器上查看了article,但不确定如何在此处应用它。
对如何解决这一挑战表示感谢。
答案 0 :(得分: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
}
}