chore(learn): Applied MDX format to Chinese curriculum files (#40462)
This commit is contained in:
@ -1,14 +1,15 @@
|
||||
---
|
||||
id: 587d7da9367417b2b2512b67
|
||||
title: 使用 concat 而不是 push 将元素添加到数组的末尾
|
||||
challengeType: 1
|
||||
forumTopicId: 301226
|
||||
title: 使用 concat 而不是 push 将元素添加到数组的末尾
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
# --description--
|
||||
|
||||
函数式编程就是创建和使用具有不变性的函数。
|
||||
上一个挑战介绍了<code>concat</code>方法,这是一种在不改变原始数组的前提下,将数组组合成新数组的方法。将<code>concat</code>方法与<code>push</code>方法做比较,<code>Push</code>将元素添加到调用它的数组的末尾,这样会改变该数组。举个例子:
|
||||
|
||||
上一个挑战介绍了`concat`方法,这是一种在不改变原始数组的前提下,将数组组合成新数组的方法。将`concat`方法与`push`方法做比较,`Push`将元素添加到调用它的数组的末尾,这样会改变该数组。举个例子:
|
||||
|
||||
```js
|
||||
var arr = [1, 2, 3];
|
||||
@ -17,67 +18,46 @@ arr.push([4, 5, 6]);
|
||||
// Not the functional programming way
|
||||
```
|
||||
|
||||
<code>Concat</code>方法可以将新项目添加到数组末尾,而不产生任何变化。
|
||||
</section>
|
||||
`Concat`方法可以将新项目添加到数组末尾,而不产生任何变化。
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
修改<code>nonMutatingPush</code>函数,用<code>concat</code>替代<code>push</code>将<code>newItem</code>添加到<code>original</code>末尾,该函数应返回一个数组。
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
修改`nonMutatingPush`函数,用`concat`替代`push`将`newItem`添加到`original`末尾,该函数应返回一个数组。
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 应该使用<code>concat</code>方法。
|
||||
testString: assert(code.match(/\.concat/g));
|
||||
- text: 不能使用<code>push</code>方法。
|
||||
testString: assert(!code.match(/\.push/g));
|
||||
- text: 不能改变<code>first</code>数组。
|
||||
testString: assert(JSON.stringify(first) === JSON.stringify([1, 2, 3]));
|
||||
- text: 不能改变<code>second</code>数组。
|
||||
testString: assert(JSON.stringify(second) === JSON.stringify([4, 5]));
|
||||
- text: <code>nonMutatingPush([1, 2, 3], [4, 5])</code>应返回<code>[1, 2, 3, 4, 5]</code>。
|
||||
testString: assert(JSON.stringify(nonMutatingPush([1, 2, 3], [4, 5])) === JSON.stringify([1, 2, 3, 4, 5]));
|
||||
# --hints--
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
应该使用`concat`方法。
|
||||
|
||||
```js
|
||||
function nonMutatingPush(original, newItem) {
|
||||
// Add your code below this line
|
||||
return original.push(newItem);
|
||||
|
||||
// Add your code above this line
|
||||
}
|
||||
var first = [1, 2, 3];
|
||||
var second = [4, 5];
|
||||
nonMutatingPush(first, second);
|
||||
assert(code.match(/\.concat/g));
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
不能使用`push`方法。
|
||||
|
||||
```js
|
||||
function nonMutatingPush(original, newItem) {
|
||||
return original.concat(newItem);
|
||||
}
|
||||
var first = [1, 2, 3];
|
||||
var second = [4, 5];
|
||||
nonMutatingPush(first, second);
|
||||
assert(!code.match(/\.push/g));
|
||||
```
|
||||
|
||||
</section>
|
||||
不能改变`first`数组。
|
||||
|
||||
```js
|
||||
assert(JSON.stringify(first) === JSON.stringify([1, 2, 3]));
|
||||
```
|
||||
|
||||
不能改变`second`数组。
|
||||
|
||||
```js
|
||||
assert(JSON.stringify(second) === JSON.stringify([4, 5]));
|
||||
```
|
||||
|
||||
`nonMutatingPush([1, 2, 3], [4, 5])`应返回`[1, 2, 3, 4, 5]`。
|
||||
|
||||
```js
|
||||
assert(
|
||||
JSON.stringify(nonMutatingPush([1, 2, 3], [4, 5])) ===
|
||||
JSON.stringify([1, 2, 3, 4, 5])
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,87 +1,70 @@
|
||||
---
|
||||
id: 587d7dab367417b2b2512b6d
|
||||
title: 应用函数式编程将字符串转换为URL片段
|
||||
challengeType: 1
|
||||
forumTopicId: 301227
|
||||
title: 应用函数式编程将字符串转换为URL片段
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
最后几个挑战中涵盖了许多符合函数式编程原则并在处理数组和字符串中非常有用的方法。我们还学习了强大的、可以将问题简化为更简单形式的<code>reduce</code>方法,从计算平均值到排序,任何数组操作都可以用它来实现。回想一下,<code>map</code>和<code>filter</code>方法都是<code>reduce</code>的特殊实现。
|
||||
# --description--
|
||||
|
||||
最后几个挑战中涵盖了许多符合函数式编程原则并在处理数组和字符串中非常有用的方法。我们还学习了强大的、可以将问题简化为更简单形式的`reduce`方法,从计算平均值到排序,任何数组操作都可以用它来实现。回想一下,`map`和`filter`方法都是`reduce`的特殊实现。
|
||||
|
||||
让我们把学到的知识结合起来解决一个实际问题。
|
||||
|
||||
许多内容管理站点(CMS)为了让添加书签更简单,会将帖子的标题添加到 URL 上。举个例子,如果你写了一篇标题为 "Stop Using Reduce" 的帖子,URL很可能会包含标题字符串的某种形式 (如:".../stop-using-reduce"),你可能已经在 freeCodeCamp 网站上注意到了这一点。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
填写<code>urlSlug</code>函数,将字符串<code>title</code>转换成带有连字符号的 URL。您可以使用本节中介绍的任何方法,但不要用<code>replace</code>方法。以下是本次挑战的要求:
|
||||
# --instructions--
|
||||
|
||||
填写`urlSlug`函数,将字符串`title`转换成带有连字符号的 URL。您可以使用本节中介绍的任何方法,但不要用`replace`方法。以下是本次挑战的要求:
|
||||
|
||||
输入包含空格和标题大小写单词的字符串
|
||||
输出字符串,单词之间的空格用连字符(<code>-</code>)替换
|
||||
|
||||
输出字符串,单词之间的空格用连字符(`-`)替换
|
||||
|
||||
输出应该是小写字母
|
||||
|
||||
输出不应有任何空格
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>globalTitle</code>变量应保持不变。
|
||||
testString: assert(globalTitle === "Winter Is Coming");
|
||||
- text: 在此挑战中不能使用<code>replace</code>方法。
|
||||
testString: assert(!code.match(/\.replace/g));
|
||||
- text: "<code>urlSlug('Winter Is Coming')</code>应返回<code>'winter-is-coming'</code>。"
|
||||
testString: assert(urlSlug("Winter Is Coming") === "winter-is-coming");
|
||||
- text: "<code>urlSlug(' Winter Is Coming')</code>应返回<code>'winter-is-coming'</code>。"
|
||||
testString: assert(urlSlug(" Winter Is Coming") === "winter-is-coming");
|
||||
- text: "<code>urlSlug('A Mind Needs Books Like A Sword Needs A Whetstone')</code>应返回<code>'a-mind-needs-books-like-a-sword-needs-a-whetstone'</code>。"
|
||||
testString: assert(urlSlug("A Mind Needs Books Like A Sword Needs A Whetstone") === "a-mind-needs-books-like-a-sword-needs-a-whetstone");
|
||||
- text: "<code>urlSlug('Hold The Door')</code>应返回<code>'hold-the-door'</code>。"
|
||||
testString: assert(urlSlug("Hold The Door") === "hold-the-door");
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
`globalTitle`变量应保持不变。
|
||||
|
||||
```js
|
||||
// the global variable
|
||||
var globalTitle = "Winter Is Coming";
|
||||
|
||||
// Add your code below this line
|
||||
function urlSlug(title) {
|
||||
|
||||
|
||||
}
|
||||
// Add your code above this line
|
||||
|
||||
var winterComing = urlSlug(globalTitle); // Should be "winter-is-coming"
|
||||
assert(globalTitle === 'Winter Is Coming');
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
在此挑战中不能使用`replace`方法。
|
||||
|
||||
```js
|
||||
// the global variable
|
||||
var globalTitle = "Winter Is Coming";
|
||||
|
||||
// Add your code below this line
|
||||
function urlSlug(title) {
|
||||
return title.trim().split(/\s+/).join("-").toLowerCase();
|
||||
}
|
||||
// Add your code above this line
|
||||
|
||||
var winterComing = urlSlug(globalTitle); // Should be "winter-is-coming"
|
||||
assert(!code.match(/\.replace/g));
|
||||
```
|
||||
|
||||
</section>
|
||||
`urlSlug('Winter Is Coming')`应返回`'winter-is-coming'`。
|
||||
|
||||
```js
|
||||
assert(urlSlug('Winter Is Coming') === 'winter-is-coming');
|
||||
```
|
||||
|
||||
`urlSlug(' Winter Is Coming')`应返回`'winter-is-coming'`。
|
||||
|
||||
```js
|
||||
assert(urlSlug(' Winter Is Coming') === 'winter-is-coming');
|
||||
```
|
||||
|
||||
`urlSlug('A Mind Needs Books Like A Sword Needs A Whetstone')`应返回`'a-mind-needs-books-like-a-sword-needs-a-whetstone'`。
|
||||
|
||||
```js
|
||||
assert(
|
||||
urlSlug('A Mind Needs Books Like A Sword Needs A Whetstone') ===
|
||||
'a-mind-needs-books-like-a-sword-needs-a-whetstone'
|
||||
);
|
||||
```
|
||||
|
||||
`urlSlug('Hold The Door')`应返回`'hold-the-door'`。
|
||||
|
||||
```js
|
||||
assert(urlSlug('Hold The Door') === 'hold-the-door');
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,76 +1,41 @@
|
||||
---
|
||||
id: 587d7b8e367417b2b2512b5e
|
||||
title: 使用函数式编程避免变化和副作用
|
||||
challengeType: 1
|
||||
forumTopicId: 301228
|
||||
title: 使用函数式编程避免变化和副作用
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
如果你还没想通,上一个挑战的问题出在<code>tabClose()</code>函数里的<code>splice</code>。不幸的是,<code>splice</code>修改了调用它的原始数组,所以第二次调用它时是基于修改后的数组,才给出了意料之外的结果。
|
||||
# --description--
|
||||
|
||||
如果你还没想通,上一个挑战的问题出在`tabClose()`函数里的`splice`。不幸的是,`splice`修改了调用它的原始数组,所以第二次调用它时是基于修改后的数组,才给出了意料之外的结果。
|
||||
|
||||
这是一个小例子,还有更广义的定义——在变量,数组或对象上调用一个函数,这个函数会改变对象中的变量或其他东西。
|
||||
|
||||
函数式编程的核心原则之一是不改变任何东西。变化会导致错误。如果一个函数不改变传入的参数、全局变量等数据,那么它造成问题的可能性就会小很多。
|
||||
前面的例子没有任何复杂的操作,但是<code>splice</code>方法改变了原始数组,导致 bug 产生。
|
||||
回想一下,在函数式编程中,改变或变更叫做<code>mutation</code>,这种改变的结果叫做“副作用”(<code>side effect</code>)。理想情况下,函数应该是不会产生任何副作用的<code>纯函数</code>。
|
||||
|
||||
前面的例子没有任何复杂的操作,但是`splice`方法改变了原始数组,导致 bug 产生。
|
||||
|
||||
回想一下,在函数式编程中,改变或变更叫做`mutation`,这种改变的结果叫做“副作用”(`side effect`)。理想情况下,函数应该是不会产生任何副作用的`纯函数`。
|
||||
|
||||
让我们尝试掌握这个原则:不要改变代码中的任何变量或对象。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
填写<code>incrementer</code>函数的代码,使其返回全局变量<code>fixedValue</code>的值增加 1。
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
填写`incrementer`函数的代码,使其返回全局变量`fixedValue`的值增加 1。
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>incrementer</code>函数不能改变<code>fixedValue</code>的值。
|
||||
testString: assert(fixedValue === 4);
|
||||
- text: <code>incrementer</code>函数应返回比<code>fixedValue</code>变量更大的值。
|
||||
testString: assert(newValue === 5);
|
||||
# --hints--
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
`incrementer`函数不能改变`fixedValue`的值。
|
||||
|
||||
```js
|
||||
// the global variable
|
||||
var fixedValue = 4;
|
||||
|
||||
function incrementer () {
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
// Add your code above this line
|
||||
}
|
||||
|
||||
var newValue = incrementer(); // Should equal 5
|
||||
console.log(fixedValue); // Should print 4
|
||||
assert(fixedValue === 4);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
`incrementer`函数应返回比`fixedValue`变量更大的值。
|
||||
|
||||
```js
|
||||
var fixedValue = 4
|
||||
|
||||
function incrementer() {
|
||||
return fixedValue + 1
|
||||
}
|
||||
|
||||
var newValue = incrementer(); // Should equal 5
|
||||
assert(newValue === 5);
|
||||
```
|
||||
|
||||
</section>
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
---
|
||||
id: 587d7daa367417b2b2512b6c
|
||||
title: 使用 join 方法将数组组合成字符串
|
||||
challengeType: 1
|
||||
forumTopicId: 18221
|
||||
title: 使用 join 方法将数组组合成字符串
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
<code>join</code>方法用来把数组中的所有元素放入一个字符串,并通过指定的分隔符参数进行分隔。
|
||||
# --description--
|
||||
|
||||
`join`方法用来把数组中的所有元素放入一个字符串,并通过指定的分隔符参数进行分隔。
|
||||
|
||||
举个例子:
|
||||
|
||||
```js
|
||||
@ -16,65 +17,52 @@ var str = arr.join(" ");
|
||||
// Sets str to "Hello World"
|
||||
```
|
||||
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
在函数<code>sentensify</code>内用<code>join</code>方法(及其他方法)用字符串<code>str</code>中的单词造句,这个函数应返回一个字符串。举个例子,"I-like-Star-Wars" 会被转换成 "I like Star Wars"。在此挑战中请勿使用<code>replace</code>方法。
|
||||
</section>
|
||||
在函数`sentensify`内用`join`方法(及其他方法)用字符串`str`中的单词造句,这个函数应返回一个字符串。举个例子,"I-like-Star-Wars" 会被转换成 "I like Star Wars"。在此挑战中请勿使用`replace`方法。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 应使用<code>join</code>方法。
|
||||
testString: assert(code.match(/\.join/g));
|
||||
- text: 不能使用<code>replace</code>方法。
|
||||
testString: assert(!code.match(/\.replace/g));
|
||||
- text: "<code>sentensify('May-the-force-be-with-you')</code>应返回一个字符串"
|
||||
testString: assert(typeof sentensify("May-the-force-be-with-you") === "string");
|
||||
- text: "<code>sentensify('May-the-force-be-with-you')</code>应返回<code>'May the force be with you'</code>。"
|
||||
testString: assert(sentensify("May-the-force-be-with-you") === "May the force be with you");
|
||||
- text: "<code>sentensify('The.force.is.strong.with.this.one')</code>应返回<code>'The force is strong with this one'</code>。"
|
||||
testString: assert(sentensify("The.force.is.strong.with.this.one") === "The force is strong with this one");
|
||||
- text: "<code>sentensify('There,has,been,an,awakening')</code>应返回<code>'There has been an awakening'</code>。"
|
||||
testString: assert(sentensify("There,has,been,an,awakening") === "There has been an awakening");
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
应使用`join`方法。
|
||||
|
||||
```js
|
||||
function sentensify(str) {
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
// Add your code above this line
|
||||
}
|
||||
sentensify("May-the-force-be-with-you");
|
||||
assert(code.match(/\.join/g));
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
不能使用`replace`方法。
|
||||
|
||||
```js
|
||||
function sentensify(str) {
|
||||
// Add your code below this line
|
||||
return str.split(/\W/).join(' ');
|
||||
// Add your code above this line
|
||||
}
|
||||
assert(!code.match(/\.replace/g));
|
||||
```
|
||||
|
||||
</section>
|
||||
`sentensify('May-the-force-be-with-you')`应返回一个字符串
|
||||
|
||||
```js
|
||||
assert(typeof sentensify('May-the-force-be-with-you') === 'string');
|
||||
```
|
||||
|
||||
`sentensify('May-the-force-be-with-you')`应返回`'May the force be with you'`。
|
||||
|
||||
```js
|
||||
assert(sentensify('May-the-force-be-with-you') === 'May the force be with you');
|
||||
```
|
||||
|
||||
`sentensify('The.force.is.strong.with.this.one')`应返回`'The force is strong with this one'`。
|
||||
|
||||
```js
|
||||
assert(
|
||||
sentensify('The.force.is.strong.with.this.one') ===
|
||||
'The force is strong with this one'
|
||||
);
|
||||
```
|
||||
|
||||
`sentensify('There,has,been,an,awakening')`应返回`'There has been an awakening'`。
|
||||
|
||||
```js
|
||||
assert(
|
||||
sentensify('There,has,been,an,awakening') === 'There has been an awakening'
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,79 +1,51 @@
|
||||
---
|
||||
id: 587d7da9367417b2b2512b66
|
||||
title: 使用 concat 方法组合两个数组
|
||||
challengeType: 1
|
||||
forumTopicId: 301229
|
||||
title: 使用 concat 方法组合两个数组
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
<code>Concatenation</code>意思是将元素连接到尾部。同理,JavaScript 为字符串和数组提供了<code>concat</code>方法。对数组来说,在一个数组上调用<code>concat</code>方法,然后提供另一个数组作为参数添加到第一个数组末尾,返回一个新数组,不会改变任何一个原始数组。举个例子:
|
||||
# --description--
|
||||
|
||||
`Concatenation`意思是将元素连接到尾部。同理,JavaScript 为字符串和数组提供了`concat`方法。对数组来说,在一个数组上调用`concat`方法,然后提供另一个数组作为参数添加到第一个数组末尾,返回一个新数组,不会改变任何一个原始数组。举个例子:
|
||||
|
||||
```js
|
||||
[1, 2, 3].concat([4, 5, 6]);
|
||||
// 返回新数组 [1, 2, 3, 4, 5, 6]
|
||||
```
|
||||
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
在<code>nonMutatingConcat</code>函数里使用<code>concat</code>,将<code>attach</code>拼接到<code>original</code>尾部,返回拼接后的数组。
|
||||
</section>
|
||||
在`nonMutatingConcat`函数里使用`concat`,将`attach`拼接到`original`尾部,返回拼接后的数组。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 应该使用<code>concat</code>方法。
|
||||
testString: assert(code.match(/\.concat/g));
|
||||
- text: 不能改变<code>first</code>数组。
|
||||
testString: assert(JSON.stringify(first) === JSON.stringify([1, 2, 3]));
|
||||
- text: 不能改变<code>second</code>数组。
|
||||
testString: assert(JSON.stringify(second) === JSON.stringify([4, 5]));
|
||||
- text: <code>nonMutatingConcat([1, 2, 3], [4, 5])</code>应返回<code>[1, 2, 3, 4, 5]</code>。
|
||||
testString: assert(JSON.stringify(nonMutatingConcat([1, 2, 3], [4, 5])) === JSON.stringify([1, 2, 3, 4, 5]));
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
应该使用`concat`方法。
|
||||
|
||||
```js
|
||||
function nonMutatingConcat(original, attach) {
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
// Add your code above this line
|
||||
}
|
||||
var first = [1, 2, 3];
|
||||
var second = [4, 5];
|
||||
nonMutatingConcat(first, second);
|
||||
assert(code.match(/\.concat/g));
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
不能改变`first`数组。
|
||||
|
||||
```js
|
||||
function nonMutatingConcat(original, attach) {
|
||||
// Add your code below this line
|
||||
return original.concat(attach);
|
||||
// Add your code above this line
|
||||
}
|
||||
var first = [1, 2, 3];
|
||||
var second = [4, 5];
|
||||
nonMutatingConcat(first, second);
|
||||
assert(JSON.stringify(first) === JSON.stringify([1, 2, 3]));
|
||||
```
|
||||
|
||||
</section>
|
||||
不能改变`second`数组。
|
||||
|
||||
```js
|
||||
assert(JSON.stringify(second) === JSON.stringify([4, 5]));
|
||||
```
|
||||
|
||||
`nonMutatingConcat([1, 2, 3], [4, 5])`应返回`[1, 2, 3, 4, 5]`。
|
||||
|
||||
```js
|
||||
assert(
|
||||
JSON.stringify(nonMutatingConcat([1, 2, 3], [4, 5])) ===
|
||||
JSON.stringify([1, 2, 3, 4, 5])
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,87 +1,37 @@
|
||||
---
|
||||
id: 587d7b8f367417b2b2512b62
|
||||
title: 在原型上实现 map 方法
|
||||
challengeType: 1
|
||||
forumTopicId: 301230
|
||||
title: 在原型上实现 map 方法
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
我们之前用<code>map</code>方法(即<code>Array.prototype.map()</code>)返回一个与调用它的数组长度相同的数组。只要它的回调函数不改变原始数组,它就不会改变原始数组。
|
||||
换句话说,<code>map</code>是一个纯函数,它的输出仅取决于输入的数组和作为参数传入的回调函数。
|
||||
为了加深对<code>map</code>方法的理解,现在我们来用<code>for</code>或<code>Array.prototype.forEach()</code>自己实现一下这个方法。
|
||||
# --description--
|
||||
|
||||
我们之前用`map`方法(即`Array.prototype.map()`)返回一个与调用它的数组长度相同的数组。只要它的回调函数不改变原始数组,它就不会改变原始数组。
|
||||
|
||||
换句话说,`map`是一个纯函数,它的输出仅取决于输入的数组和作为参数传入的回调函数。
|
||||
|
||||
为了加深对`map`方法的理解,现在我们来用`for`或`Array.prototype.forEach()`自己实现一下这个方法。
|
||||
|
||||
注意:纯函数可以改变其作用域内定义的局部变量,但我们最好不要这样做。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
写一个和<code>Array.prototype.map()</code>一样的<code>Array.prototype.myMap()</code>。你可以用<code>for</code>循环或者<code>forEach</code>方法。
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
写一个和`Array.prototype.map()`一样的`Array.prototype.myMap()`。你可以用`for`循环或者`forEach`方法。
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>new_s</code>应等于<code>[46, 130, 196, 10]</code>。
|
||||
testString: assert(JSON.stringify(new_s) === JSON.stringify([46, 130, 196, 10]));
|
||||
- text: 不能使用<code>map</code>方法。
|
||||
testString: assert(!code.match(/\.map/g));
|
||||
# --hints--
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
`new_s`应等于`[46, 130, 196, 10]`。
|
||||
|
||||
```js
|
||||
// the global Array
|
||||
var s = [23, 65, 98, 5];
|
||||
|
||||
Array.prototype.myMap = function(callback){
|
||||
var newArray = [];
|
||||
// Add your code below this line
|
||||
|
||||
// Add your code above this line
|
||||
return newArray;
|
||||
|
||||
};
|
||||
|
||||
var new_s = s.myMap(function(item){
|
||||
return item * 2;
|
||||
});
|
||||
assert(JSON.stringify(new_s) === JSON.stringify([46, 130, 196, 10]));
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
不能使用`map`方法。
|
||||
|
||||
```js
|
||||
// the global Array
|
||||
var s = [23, 65, 98, 5];
|
||||
|
||||
Array.prototype.myMap = function(callback){
|
||||
var newArray = [];
|
||||
// Add your code below this line
|
||||
for (var elem of this) {
|
||||
newArray.push(callback(elem));
|
||||
}
|
||||
// Add your code above this line
|
||||
return newArray;
|
||||
|
||||
};
|
||||
|
||||
var new_s = s.myMap(function(item){
|
||||
return item * 2;
|
||||
});
|
||||
assert(!code.match(/\.map/g));
|
||||
```
|
||||
|
||||
</section>
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,85 +1,33 @@
|
||||
---
|
||||
id: 587d7b8f367417b2b2512b64
|
||||
title: 在原型上实现 filter 方法
|
||||
challengeType: 1
|
||||
forumTopicId: 301231
|
||||
title: 在原型上实现 filter 方法
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
为了加深对<code>filter</code>的理解,现在我们来自己实现一下<code>Array.prototype.filter()</code>方法。可以用<code>for</code>循环或<code>Array.prototype.forEach()</code>。
|
||||
# --description--
|
||||
|
||||
为了加深对`filter`的理解,现在我们来自己实现一下`Array.prototype.filter()`方法。可以用`for`循环或`Array.prototype.forEach()`。
|
||||
|
||||
请注意:纯函数可以改变其作用域内定义的局部变量,但我们最好不要这样做。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
编写一个和<code>Array.prototype.filter()</code>功能一样的<code>Array.prototype.myFilter()</code>方法。你可以用<code>for</code>循环或<code>Array.prototype.forEach()</code>方法。
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
编写一个和`Array.prototype.filter()`功能一样的`Array.prototype.myFilter()`方法。你可以用`for`循环或`Array.prototype.forEach()`方法。
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>new_s</code>应等于<code>[23, 65, 5]</code>。
|
||||
testString: assert(JSON.stringify(new_s) === JSON.stringify([23, 65, 5]));
|
||||
- text: 不能使用<code>filter</code>方法。
|
||||
testString: assert(!code.match(/\.filter/g));
|
||||
# --hints--
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
`new_s`应等于`[23, 65, 5]`。
|
||||
|
||||
```js
|
||||
// the global Array
|
||||
var s = [23, 65, 98, 5];
|
||||
|
||||
Array.prototype.myFilter = function(callback){
|
||||
var newArray = [];
|
||||
// Add your code below this line
|
||||
|
||||
// Add your code above this line
|
||||
return newArray;
|
||||
|
||||
};
|
||||
|
||||
var new_s = s.myFilter(function(item){
|
||||
return item % 2 === 1;
|
||||
});
|
||||
assert(JSON.stringify(new_s) === JSON.stringify([23, 65, 5]));
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
不能使用`filter`方法。
|
||||
|
||||
```js
|
||||
// the global Array
|
||||
var s = [23, 65, 98, 5];
|
||||
|
||||
Array.prototype.myFilter = function(callback){
|
||||
var newArray = [];
|
||||
// Add your code below this line
|
||||
for (let i = 0;i<this.length;i++) {
|
||||
if (callback(this[i]))
|
||||
newArray.push(this[i]);
|
||||
}
|
||||
// Add your code above this line
|
||||
return newArray;
|
||||
};
|
||||
|
||||
var new_s = s.myFilter(function(item){
|
||||
return item % 2 === 1;
|
||||
});
|
||||
assert(!code.match(/\.filter/g));
|
||||
```
|
||||
|
||||
</section>
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,14 +1,16 @@
|
||||
---
|
||||
id: 587d7dab367417b2b2512b70
|
||||
title: 函数柯里化
|
||||
challengeType: 1
|
||||
forumTopicId: 301232
|
||||
title: 函数柯里化
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
<code>arity</code>是函数所需的形参的数量。函数<code>柯里化</code>意思是把接受多个<code>arity</code>的函数变换成接受单一<code>arity</code>的函数。
|
||||
# --description--
|
||||
|
||||
`arity`是函数所需的形参的数量。函数`柯里化`意思是把接受多个`arity`的函数变换成接受单一`arity`的函数。
|
||||
|
||||
换句话说,就是重构函数让它接收一个参数,然后返回接收下一个参数的函数,依此类推。
|
||||
|
||||
举个例子:
|
||||
|
||||
```js
|
||||
@ -29,7 +31,7 @@ const curried = x => y => x + y
|
||||
curried(1)(2) // 返回 3
|
||||
```
|
||||
|
||||
柯里化在不能一次为函数提供所有参数情况下很有用。因为它可以将每个函数的调用保存到一个变量中,该变量将保存返回的函数引用,该引用在下一个参数可用时接受该参数。下面是使用<code>柯里化</code>函数的例子:
|
||||
柯里化在不能一次为函数提供所有参数情况下很有用。因为它可以将每个函数的调用保存到一个变量中,该变量将保存返回的函数引用,该引用在下一个参数可用时接受该参数。下面是使用`柯里化`函数的例子:
|
||||
|
||||
```js
|
||||
// Call a curried function in parts:
|
||||
@ -37,8 +39,7 @@ var funcForY = curried(1);
|
||||
console.log(funcForY(2)); // Prints 3
|
||||
```
|
||||
|
||||
类似地,<code>局部应用</code>的意思是一次对一个函数应用几个参数,然后返回另一个应用更多参数的函数。
|
||||
举个例子:
|
||||
类似地,`局部应用`的意思是一次对一个函数应用几个参数,然后返回另一个应用更多参数的函数。 举个例子:
|
||||
|
||||
```js
|
||||
//Impartial function
|
||||
@ -49,57 +50,35 @@ var partialFn = impartial.bind(this, 1, 2);
|
||||
partialFn(10); // Returns 13
|
||||
```
|
||||
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
填写<code>add</code>函数主体部分,用柯里化添加参数<code>x</code>,<code>y</code>和<code>z</code>.
|
||||
</section>
|
||||
填写`add`函数主体部分,用柯里化添加参数`x`,`y`和`z`.
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>add(10)(20)(30)</code>应返回<code>60</code>。
|
||||
testString: assert(add(10)(20)(30) === 60);
|
||||
- text: <code>add(1)(2)(3)</code>应返回<code>6</code>。
|
||||
testString: assert(add(1)(2)(3) === 6);
|
||||
- text: <code>add(11)(22)(33)</code>应返回<code>66</code>。
|
||||
testString: assert(add(11)(22)(33) === 66);
|
||||
- text: 应返回<code>x + y + z</code>的最终结果。
|
||||
testString: assert(code.match(/[xyz]\s*?\+\s*?[xyz]\s*?\+\s*?[xyz]/g));
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
`add(10)(20)(30)`应返回`60`。
|
||||
|
||||
```js
|
||||
function add(x) {
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
// Add your code above this line
|
||||
}
|
||||
add(10)(20)(30);
|
||||
assert(add(10)(20)(30) === 60);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
`add(1)(2)(3)`应返回`6`。
|
||||
|
||||
```js
|
||||
const add = x => y => z => x + y + z
|
||||
assert(add(1)(2)(3) === 6);
|
||||
```
|
||||
|
||||
</section>
|
||||
`add(11)(22)(33)`应返回`66`。
|
||||
|
||||
```js
|
||||
assert(add(11)(22)(33) === 66);
|
||||
```
|
||||
|
||||
应返回`x + y + z`的最终结果。
|
||||
|
||||
```js
|
||||
assert(code.match(/[xyz]\s*?\+\s*?[xyz]\s*?\+\s*?[xyz]/g));
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,102 +1,43 @@
|
||||
---
|
||||
id: 587d7b8d367417b2b2512b5b
|
||||
title: 学习函数式编程
|
||||
challengeType: 1
|
||||
forumTopicId: 301233
|
||||
title: 学习函数式编程
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
# --description--
|
||||
|
||||
函数式编程是一种方案简单、功能独立、对作用域外没有任何副作用的编程范式。
|
||||
<code>INPUT -> PROCESS -> OUTPUT</code>
|
||||
|
||||
`INPUT -> PROCESS -> OUTPUT`
|
||||
|
||||
函数式编程:
|
||||
|
||||
1)功能独立——不依赖于程序的状态(比如可能发生变化的全局变量);
|
||||
|
||||
2)纯函数——同一个输入永远能得到同一个输出;
|
||||
|
||||
3)有限的副作用——可以严格地限制函数外部对状态的更改。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
# --instructions--
|
||||
|
||||
freeCodeCamp 成员在 love tea 的故事。
|
||||
在代码编辑器中,已经为你定义好了<code>prepareTea</code>和<code>getTea</code>函数。调用<code>getTea</code>函数为团队准备 40 杯茶,并将它们存储在<code>tea4TeamFCC</code>变量里。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
在代码编辑器中,已经为你定义好了`prepareTea`和`getTea`函数。调用`getTea`函数为团队准备 40 杯茶,并将它们存储在`tea4TeamFCC`变量里。
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>tea4TeamFCC</code>变量里应有 40 杯为团队准备的茶。
|
||||
testString: assert(tea4TeamFCC.length === 40);
|
||||
- text: <code>tea4TeamFCC</code>变量里应有 greenTea。
|
||||
testString: assert(tea4TeamFCC[0] === 'greenTea');
|
||||
# --hints--
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
`tea4TeamFCC`变量里应有 40 杯为团队准备的茶。
|
||||
|
||||
```js
|
||||
/**
|
||||
* A long process to prepare tea.
|
||||
* @return {string} A cup of tea.
|
||||
**/
|
||||
const prepareTea = () => 'greenTea';
|
||||
|
||||
/**
|
||||
* Get given number of cups of tea.
|
||||
* @param {number} numOfCups Number of required cups of tea.
|
||||
* @return {Array<string>} Given amount of tea cups.
|
||||
**/
|
||||
const getTea = (numOfCups) => {
|
||||
const teaCups = [];
|
||||
|
||||
for(let cups = 1; cups <= numOfCups; cups += 1) {
|
||||
const teaCup = prepareTea();
|
||||
teaCups.push(teaCup);
|
||||
}
|
||||
|
||||
return teaCups;
|
||||
};
|
||||
|
||||
// Add your code below this line
|
||||
|
||||
const tea4TeamFCC = null; // :(
|
||||
|
||||
// Add your code above this line
|
||||
|
||||
console.log(tea4TeamFCC);
|
||||
assert(tea4TeamFCC.length === 40);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
`tea4TeamFCC`变量里应有 greenTea。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
const prepareTea = () => 'greenTea';
|
||||
|
||||
const getTea = (numOfCups) => {
|
||||
const teaCups = [];
|
||||
|
||||
for(let cups = 1; cups <= numOfCups; cups += 1) {
|
||||
const teaCup = prepareTea();
|
||||
teaCups.push(teaCup);
|
||||
}
|
||||
|
||||
return teaCups;
|
||||
};
|
||||
|
||||
const tea4TeamFCC = getTea(40);
|
||||
assert(tea4TeamFCC[0] === 'greenTea');
|
||||
```
|
||||
|
||||
</section>
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,79 +1,49 @@
|
||||
---
|
||||
id: 587d7b8e367417b2b2512b5f
|
||||
title: 传递参数以避免函数中的外部依赖
|
||||
challengeType: 1
|
||||
forumTopicId: 301234
|
||||
title: 传递参数以避免函数中的外部依赖
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
# --description--
|
||||
|
||||
上一个挑战是更接近函数式编程原则的挑战,但是仍然缺少一些东西。
|
||||
虽然我们没有改变全局变量值,但在没有全局变量<code>fixedValue</code>情况下,<code>incrementer</code>函数将不起作用。
|
||||
|
||||
虽然我们没有改变全局变量值,但在没有全局变量`fixedValue`情况下,`incrementer`函数将不起作用。
|
||||
|
||||
函数式编程的另一个原则是:总是显式声明依赖关系。如果函数依赖于一个变量或对象,那么将该变量或对象作为参数直接传递到函数中。
|
||||
|
||||
这样做会有很多好处,其中一点是让函数更容易测试,因为你确切地知道参数是什么,并且这个参数也不依赖于程序中的任何其他内容。
|
||||
|
||||
其次,这样做可以让你更加自信地更改,删除或添加新代码。因为你很清楚哪些是可以改的,哪些是不可以改的,这样你就知道哪里可能会有潜在的陷阱。
|
||||
|
||||
最后,无论代码的哪一部分执行它,函数总是会为同一组输入生成相同的输出。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
更新<code>incrementer</code>函数,明确声明其依赖项。
|
||||
编写<code>incrementer</code>函数,获取它的参数,然后将值增加 1。
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
更新`incrementer`函数,明确声明其依赖项。
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>incrementer</code>函数不能修改<code>fixedValue</code>的值。
|
||||
testString: assert(fixedValue === 4);
|
||||
- text: <code>incrementer</code>函数应该接收一个参数。
|
||||
testString: assert(incrementer.length === 1);
|
||||
- text: <code>incrementer</code>函数应返回比<code>fixedValue</code>更大的值。
|
||||
testString: assert(newValue === 5);
|
||||
编写`incrementer`函数,获取它的参数,然后将值增加 1。
|
||||
|
||||
```
|
||||
# --hints--
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
`incrementer`函数不能修改`fixedValue`的值。
|
||||
|
||||
```js
|
||||
// the global variable
|
||||
var fixedValue = 4;
|
||||
|
||||
// Add your code below this line
|
||||
function incrementer () {
|
||||
|
||||
|
||||
// Add your code above this line
|
||||
}
|
||||
|
||||
var newValue = incrementer(fixedValue); // Should equal 5
|
||||
console.log(fixedValue); // Should print 4
|
||||
assert(fixedValue === 4);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
`incrementer`函数应该接收一个参数。
|
||||
|
||||
```js
|
||||
// the global variable
|
||||
var fixedValue = 4;
|
||||
|
||||
const incrementer = val => val + 1;
|
||||
|
||||
var newValue = incrementer(fixedValue); // Should equal 5
|
||||
console.log(fixedValue); // Should print 4
|
||||
assert(incrementer.length === 1);
|
||||
```
|
||||
|
||||
</section>
|
||||
`incrementer`函数应返回比`fixedValue`更大的值。
|
||||
|
||||
```js
|
||||
assert(newValue === 5);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,123 +1,81 @@
|
||||
---
|
||||
id: 587d7b8f367417b2b2512b60
|
||||
title: 在函数中重构全局变量
|
||||
challengeType: 1
|
||||
forumTopicId: 301235
|
||||
title: 在函数中重构全局变量
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
# --description--
|
||||
|
||||
目前为止,我们已经看到了函数式编程的两个原则:
|
||||
|
||||
1) 不要更改变量或对象——创建新变量和对象,并在需要时从函数返回它们。
|
||||
|
||||
2) 声明函数参数——函数内的任何计算仅取决于参数,而不取决于任何全局对象或变量。
|
||||
|
||||
给数字增加 1 不够刺激,我们可以在处理数组或更复杂的对象时应用这些原则。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
重构代码,使全局数组<code>bookList</code>在函数内部不会被改变。<code>add</code>函数可以将指定的<code>bookName</code>增加到数组末尾。<code>remove</code>函数可以从数组中移除指定<code>bookName</code>。两个函数都返回数组,并且任何参数都应该添加到<code>bookName</code>前面。
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
重构代码,使全局数组`bookList`在函数内部不会被改变。`add`函数可以将指定的`bookName`增加到数组末尾。`remove`函数可以从数组中移除指定`bookName`。两个函数都返回数组,并且任何参数都应该添加到`bookName`前面。
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: "<code>bookList</code>不应该改变,应等于<code>['The Hound of the Baskervilles', 'On The Electrodynamics of Moving Bodies', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae']</code>."
|
||||
testString: assert(JSON.stringify(bookList) === JSON.stringify(["The Hound of the Baskervilles", "On The Electrodynamics of Moving Bodies", "Philosophiæ Naturalis Principia Mathematica", "Disquisitiones Arithmeticae"]));
|
||||
- text: "<code>newBookList</code>应等于<code>['The Hound of the Baskervilles', 'On The Electrodynamics of Moving Bodies', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae', 'A Brief History of Time']</code>."
|
||||
testString: assert(JSON.stringify(newBookList) === JSON.stringify(['The Hound of the Baskervilles', 'On The Electrodynamics of Moving Bodies', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae', 'A Brief History of Time']));
|
||||
- text: "<code>newerBookList</code>应等于<code>['The Hound of the Baskervilles', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae']</code>."
|
||||
testString: assert(JSON.stringify(newerBookList) === JSON.stringify(['The Hound of the Baskervilles', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae']));
|
||||
- text: "<code>newestBookList</code>应等于<code>['The Hound of the Baskervilles', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae', 'A Brief History of Time']</code>."
|
||||
testString: assert(JSON.stringify(newestBookList) === JSON.stringify(['The Hound of the Baskervilles', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae', 'A Brief History of Time']));
|
||||
# --hints--
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
`bookList`不应该改变,应等于`['The Hound of the Baskervilles', 'On The Electrodynamics of Moving Bodies', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae']`.
|
||||
|
||||
```js
|
||||
// the global variable
|
||||
var bookList = ["The Hound of the Baskervilles", "On The Electrodynamics of Moving Bodies", "Philosophiæ Naturalis Principia Mathematica", "Disquisitiones Arithmeticae"];
|
||||
|
||||
/* This function should add a book to the list and return the list */
|
||||
// New parameters should come before bookName
|
||||
|
||||
// Add your code below this line
|
||||
function add (bookName) {
|
||||
|
||||
bookList.push(bookName);
|
||||
return bookList;
|
||||
|
||||
// Add your code above this line
|
||||
}
|
||||
|
||||
/* This function should remove a book from the list and return the list */
|
||||
// New parameters should come before the bookName one
|
||||
|
||||
// Add your code below this line
|
||||
function remove (bookName) {
|
||||
var book_index = bookList.indexOf(bookName);
|
||||
if (book_index >= 0) {
|
||||
|
||||
bookList.splice(book_index, 1);
|
||||
return bookList;
|
||||
|
||||
// Add your code above this line
|
||||
}
|
||||
}
|
||||
|
||||
var newBookList = add(bookList, 'A Brief History of Time');
|
||||
var newerBookList = remove(bookList, 'On The Electrodynamics of Moving Bodies');
|
||||
var newestBookList = remove(add(bookList, 'A Brief History of Time'), 'On The Electrodynamics of Moving Bodies');
|
||||
|
||||
console.log(bookList);
|
||||
assert(
|
||||
JSON.stringify(bookList) ===
|
||||
JSON.stringify([
|
||||
'The Hound of the Baskervilles',
|
||||
'On The Electrodynamics of Moving Bodies',
|
||||
'Philosophiæ Naturalis Principia Mathematica',
|
||||
'Disquisitiones Arithmeticae'
|
||||
])
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
`newBookList`应等于`['The Hound of the Baskervilles', 'On The Electrodynamics of Moving Bodies', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae', 'A Brief History of Time']`.
|
||||
|
||||
```js
|
||||
// the global variable
|
||||
var bookList = ["The Hound of the Baskervilles", "On The Electrodynamics of Moving Bodies", "Philosophiæ Naturalis Principia Mathematica", "Disquisitiones Arithmeticae"];
|
||||
|
||||
/* This function should add a book to the list and return the list */
|
||||
// New parameters should come before the bookName one
|
||||
|
||||
// Add your code below this line
|
||||
function add (bookList, bookName) {
|
||||
return [...bookList, bookName];
|
||||
// Add your code above this line
|
||||
}
|
||||
|
||||
/* This function should remove a book from the list and return the list */
|
||||
// New parameters should come before the bookName one
|
||||
|
||||
// Add your code below this line
|
||||
function remove (bookList, bookName) {
|
||||
const bookListCopy = [...bookList];
|
||||
const bookNameIndex = bookList.indexOf(bookName);
|
||||
if (bookNameIndex >= 0) {
|
||||
bookListCopy.splice(bookNameIndex, 1);
|
||||
}
|
||||
return bookListCopy;
|
||||
// Add your code above this line
|
||||
}
|
||||
|
||||
var newBookList = add(bookList, 'A Brief History of Time');
|
||||
var newerBookList = remove(bookList, 'On The Electrodynamics of Moving Bodies');
|
||||
var newestBookList = remove(add(bookList, 'A Brief History of Time'), 'On The Electrodynamics of Moving Bodies');
|
||||
assert(
|
||||
JSON.stringify(newBookList) ===
|
||||
JSON.stringify([
|
||||
'The Hound of the Baskervilles',
|
||||
'On The Electrodynamics of Moving Bodies',
|
||||
'Philosophiæ Naturalis Principia Mathematica',
|
||||
'Disquisitiones Arithmeticae',
|
||||
'A Brief History of Time'
|
||||
])
|
||||
);
|
||||
```
|
||||
|
||||
</section>
|
||||
`newerBookList`应等于`['The Hound of the Baskervilles', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae']`.
|
||||
|
||||
```js
|
||||
assert(
|
||||
JSON.stringify(newerBookList) ===
|
||||
JSON.stringify([
|
||||
'The Hound of the Baskervilles',
|
||||
'Philosophiæ Naturalis Principia Mathematica',
|
||||
'Disquisitiones Arithmeticae'
|
||||
])
|
||||
);
|
||||
```
|
||||
|
||||
`newestBookList`应等于`['The Hound of the Baskervilles', 'Philosophiæ Naturalis Principia Mathematica', 'Disquisitiones Arithmeticae', 'A Brief History of Time']`.
|
||||
|
||||
```js
|
||||
assert(
|
||||
JSON.stringify(newestBookList) ===
|
||||
JSON.stringify([
|
||||
'The Hound of the Baskervilles',
|
||||
'Philosophiæ Naturalis Principia Mathematica',
|
||||
'Disquisitiones Arithmeticae',
|
||||
'A Brief History of Time'
|
||||
])
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
---
|
||||
id: 9d7123c8c441eeafaeb5bdef
|
||||
title: 使用 slice 而不是 splice 从数组中移除元素
|
||||
challengeType: 1
|
||||
forumTopicId: 301236
|
||||
title: 使用 slice 而不是 splice 从数组中移除元素
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
使用数组时经常遇到要删除一些元素并保留数组剩余部分的情况。为此,JavaScript 提供了<code>splice</code>方法,它接收两个参数:从哪里开始删除项目的索引,和要删除的项目数。如果没有提供第二个参数,默认情况下是移除到结尾的元素。但<code>splice</code>方法会改变调用它的原始数组。举个例子:
|
||||
# --description--
|
||||
|
||||
使用数组时经常遇到要删除一些元素并保留数组剩余部分的情况。为此,JavaScript 提供了`splice`方法,它接收两个参数:从哪里开始删除项目的索引,和要删除的项目数。如果没有提供第二个参数,默认情况下是移除到结尾的元素。但`splice`方法会改变调用它的原始数组。举个例子:
|
||||
|
||||
```js
|
||||
var cities = ["Chicago", "Delhi", "Islamabad", "London", "Berlin"];
|
||||
@ -15,66 +15,46 @@ cities.splice(3, 1); // Returns "London" and deletes it from the cities array
|
||||
// cities is now ["Chicago", "Delhi", "Islamabad", "Berlin"]
|
||||
```
|
||||
|
||||
正如我们在上一次挑战中看到的那样,<code>slice</code>方法不会改变原始数组,而是返回一个可以保存到变量中的新数组。回想一下,<code>slice</code>方法接收两个参数,从开始索引开始选取到结束(不包括该元素),并在新数组中返回这些元素。使用<code>slice</code>方法替代<code>splice</code>有助于避免数组变化产生的副作用。
|
||||
</section>
|
||||
正如我们在上一次挑战中看到的那样,`slice`方法不会改变原始数组,而是返回一个可以保存到变量中的新数组。回想一下,`slice`方法接收两个参数,从开始索引开始选取到结束(不包括该元素),并在新数组中返回这些元素。使用`slice`方法替代`splice`有助于避免数组变化产生的副作用。
|
||||
|
||||
# --instructions--
|
||||
|
||||
用`slice`代替`splice`重写`nonMutatingSplice`函数。将`cities`数组长度限制为3,并返回一个仅包含前 3 项的新数组。
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
用<code>slice</code>代替<code>splice</code>重写<code>nonMutatingSplice</code>函数。将<code>cities</code>数组长度限制为3,并返回一个仅包含前 3 项的新数组。
|
||||
不要改变提供给函数的原始数组。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 应该使用<code>slice</code>方法。
|
||||
testString: assert(code.match(/\.slice/g));
|
||||
- text: 不能使用<code>splice</code>方法。
|
||||
testString: assert(!code.match(/\.splice/g));
|
||||
- text: 不能改变<code>inputCities</code>数组。
|
||||
testString: assert(JSON.stringify(inputCities) === JSON.stringify(["Chicago", "Delhi", "Islamabad", "London", "Berlin"]));
|
||||
- text: "<code>nonMutatingSplice(['Chicago', 'Delhi', 'Islamabad', 'London', 'Berlin'])</code>应返回<code>['Chicago', 'Delhi', 'Islamabad']</code>。"
|
||||
testString: assert(JSON.stringify(nonMutatingSplice(["Chicago", "Delhi", "Islamabad", "London", "Berlin"])) === JSON.stringify(["Chicago", "Delhi", "Islamabad"]));
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
应该使用`slice`方法。
|
||||
|
||||
```js
|
||||
function nonMutatingSplice(cities) {
|
||||
// Add your code below this line
|
||||
return cities.splice(3);
|
||||
|
||||
// Add your code above this line
|
||||
}
|
||||
var inputCities = ["Chicago", "Delhi", "Islamabad", "London", "Berlin"];
|
||||
nonMutatingSplice(inputCities);
|
||||
assert(code.match(/\.slice/g));
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
不能使用`splice`方法。
|
||||
|
||||
```js
|
||||
function nonMutatingSplice(cities) {
|
||||
// Add your code below this line
|
||||
return cities.slice(0,3);
|
||||
// Add your code above this line
|
||||
}
|
||||
var inputCities = ["Chicago", "Delhi", "Islamabad", "London", "Berlin"];
|
||||
nonMutatingSplice(inputCities);
|
||||
assert(!code.match(/\.splice/g));
|
||||
```
|
||||
|
||||
</section>
|
||||
不能改变`inputCities`数组。
|
||||
|
||||
```js
|
||||
assert(
|
||||
JSON.stringify(inputCities) ===
|
||||
JSON.stringify(['Chicago', 'Delhi', 'Islamabad', 'London', 'Berlin'])
|
||||
);
|
||||
```
|
||||
|
||||
`nonMutatingSplice(['Chicago', 'Delhi', 'Islamabad', 'London', 'Berlin'])`应返回`['Chicago', 'Delhi', 'Islamabad']`。
|
||||
|
||||
```js
|
||||
assert(
|
||||
JSON.stringify(
|
||||
nonMutatingSplice(['Chicago', 'Delhi', 'Islamabad', 'London', 'Berlin'])
|
||||
) === JSON.stringify(['Chicago', 'Delhi', 'Islamabad'])
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,71 +1,46 @@
|
||||
---
|
||||
id: 587d7da9367417b2b2512b6a
|
||||
title: 在不更改原始数组的前提下返回排序后的数组
|
||||
challengeType: 1
|
||||
forumTopicId: 301237
|
||||
title: 在不更改原始数组的前提下返回排序后的数组
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
<code>sort</code>方法会产生改变原始数组中元素顺序的副作用。换句话说,它会改变数组的位置。避免这种情况的一种方法是先将空数组连接到正在排序的数组上(记住<code>concat</code>返回一个新数组),再用<code>sort</code>方法。
|
||||
</section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
在<code>nonMutatingSort</code>函数中使用<code>sort</code>方法对数组中的元素按升序进行排列。函数不能改变<code>globalArray</code>变量,应返回一个新数组。
|
||||
</section>
|
||||
`sort`方法会产生改变原始数组中元素顺序的副作用。换句话说,它会改变数组的位置。避免这种情况的一种方法是先将空数组连接到正在排序的数组上(记住`concat`返回一个新数组),再用`sort`方法。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --instructions--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 应该使用<code>sort</code>方法。
|
||||
testString: assert(nonMutatingSort.toString().match(/\.sort/g));
|
||||
- text: 应该使用<code>concat</code>方法。
|
||||
testString: assert(JSON.stringify(globalArray) === JSON.stringify([5, 6, 3, 2, 9]));
|
||||
- text: <code>globalArray</code>variable 应保持不变。
|
||||
testString: assert(JSON.stringify(nonMutatingSort(globalArray)) === JSON.stringify([2, 3, 5, 6, 9]));
|
||||
- text: <code>nonMutatingSort(globalArray)</code>应返回<code>[2, 3, 5, 6, 9]</code>。
|
||||
testString: assert(!nonMutatingSort.toString().match(/[23569]/g));
|
||||
在`nonMutatingSort`函数中使用`sort`方法对数组中的元素按升序进行排列。函数不能改变`globalArray`变量,应返回一个新数组。
|
||||
|
||||
```
|
||||
# --hints--
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
应该使用`sort`方法。
|
||||
|
||||
```js
|
||||
var globalArray = [5, 6, 3, 2, 9];
|
||||
function nonMutatingSort(arr) {
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
// Add your code above this line
|
||||
}
|
||||
nonMutatingSort(globalArray);
|
||||
assert(nonMutatingSort.toString().match(/\.sort/g));
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
应该使用`concat`方法。
|
||||
|
||||
```js
|
||||
var globalArray = [5, 6, 3, 2, 9];
|
||||
function nonMutatingSort(arr) {
|
||||
// Add your code below this line
|
||||
return [].concat(arr).sort((a,b) => a-b);
|
||||
// Add your code above this line
|
||||
}
|
||||
nonMutatingSort(globalArray);
|
||||
assert(JSON.stringify(globalArray) === JSON.stringify([5, 6, 3, 2, 9]));
|
||||
```
|
||||
|
||||
</section>
|
||||
`globalArray`variable 应保持不变。
|
||||
|
||||
```js
|
||||
assert(
|
||||
JSON.stringify(nonMutatingSort(globalArray)) ===
|
||||
JSON.stringify([2, 3, 5, 6, 9])
|
||||
);
|
||||
```
|
||||
|
||||
`nonMutatingSort(globalArray)`应返回`[2, 3, 5, 6, 9]`。
|
||||
|
||||
```js
|
||||
assert(!nonMutatingSort.toString().match(/[23569]/g));
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
---
|
||||
id: 587d7b90367417b2b2512b65
|
||||
title: 使用 slice 方法返回数组的一部分
|
||||
challengeType: 1
|
||||
forumTopicId: 301239
|
||||
title: 使用 slice 方法返回数组的一部分
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
<code>slice</code>方法可以从已有数组中返回指定元素。它接受两个参数,第一个规定从何处开始选取,第二个规定从何处结束选取(不包括该元素)。如果没有传参,则默认为从数组的开头开始到结尾结束,这是复制整个数组的简单方式。<code>slice</code>返回一个新数组,不会修改原始数组。
|
||||
# --description--
|
||||
|
||||
`slice`方法可以从已有数组中返回指定元素。它接受两个参数,第一个规定从何处开始选取,第二个规定从何处结束选取(不包括该元素)。如果没有传参,则默认为从数组的开头开始到结尾结束,这是复制整个数组的简单方式。`slice`返回一个新数组,不会修改原始数组。
|
||||
|
||||
举个例子:
|
||||
|
||||
```js
|
||||
@ -16,66 +17,53 @@ var newArray = arr.slice(1, 3);
|
||||
// Sets newArray to ["Dog", "Tiger"]
|
||||
```
|
||||
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
在<code>sliceArray</code>函数中使用<code>slice</code>方法,给出<code>beginSlice</code>和<code>endSlice</code>索引,返回<code>anim</code>数组的一部分,这个函数应返回一个数组。
|
||||
</section>
|
||||
在`sliceArray`函数中使用`slice`方法,给出`beginSlice`和`endSlice`索引,返回`anim`数组的一部分,这个函数应返回一个数组。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 你的代码中应使用<code>slice</code>方法。
|
||||
testString: assert(code.match(/\.slice/g));
|
||||
- text: 不能改变<code>inputAnim</code>变量。
|
||||
testString: assert(JSON.stringify(inputAnim) === JSON.stringify(["Cat", "Dog", "Tiger", "Zebra", "Ant"]));
|
||||
- text: "<code>sliceArray(['Cat', 'Dog', 'Tiger', 'Zebra', 'Ant'], 1, 3)</code>应返回<code>['Dog', 'Tiger']</code>。"
|
||||
testString: assert(JSON.stringify(sliceArray(["Cat", "Dog", "Tiger", "Zebra", "Ant"], 1, 3)) === JSON.stringify(["Dog", "Tiger"]));
|
||||
- text: "<code>sliceArray(['Cat', 'Dog', 'Tiger', 'Zebra', 'Ant'], 0, 1)</code>应返回<code>['Cat']</code>。"
|
||||
testString: assert(JSON.stringify(sliceArray(["Cat", "Dog", "Tiger", "Zebra", "Ant"], 0, 1)) === JSON.stringify(["Cat"]));
|
||||
- text: "<code>sliceArray(['Cat', 'Dog', 'Tiger', 'Zebra', 'Ant'], 1, 4)</code>应返回<code>['Dog', 'Tiger', 'Zebra']</code>。"
|
||||
testString: assert(JSON.stringify(sliceArray(["Cat", "Dog", "Tiger", "Zebra", "Ant"], 1, 4)) === JSON.stringify(["Dog", "Tiger", "Zebra"]));
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
你的代码中应使用`slice`方法。
|
||||
|
||||
```js
|
||||
function sliceArray(anim, beginSlice, endSlice) {
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
// Add your code above this line
|
||||
}
|
||||
var inputAnim = ["Cat", "Dog", "Tiger", "Zebra", "Ant"];
|
||||
sliceArray(inputAnim, 1, 3);
|
||||
assert(code.match(/\.slice/g));
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
不能改变`inputAnim`变量。
|
||||
|
||||
```js
|
||||
function sliceArray(anim, beginSlice, endSlice) {
|
||||
// Add your code below this line
|
||||
return anim.slice(beginSlice, endSlice)
|
||||
// Add your code above this line
|
||||
}
|
||||
var inputAnim = ["Cat", "Dog", "Tiger", "Zebra", "Ant"];
|
||||
sliceArray(inputAnim, 1, 3);
|
||||
assert(
|
||||
JSON.stringify(inputAnim) ===
|
||||
JSON.stringify(['Cat', 'Dog', 'Tiger', 'Zebra', 'Ant'])
|
||||
);
|
||||
```
|
||||
|
||||
</section>
|
||||
`sliceArray(['Cat', 'Dog', 'Tiger', 'Zebra', 'Ant'], 1, 3)`应返回`['Dog', 'Tiger']`。
|
||||
|
||||
```js
|
||||
assert(
|
||||
JSON.stringify(sliceArray(['Cat', 'Dog', 'Tiger', 'Zebra', 'Ant'], 1, 3)) ===
|
||||
JSON.stringify(['Dog', 'Tiger'])
|
||||
);
|
||||
```
|
||||
|
||||
`sliceArray(['Cat', 'Dog', 'Tiger', 'Zebra', 'Ant'], 0, 1)`应返回`['Cat']`。
|
||||
|
||||
```js
|
||||
assert(
|
||||
JSON.stringify(sliceArray(['Cat', 'Dog', 'Tiger', 'Zebra', 'Ant'], 0, 1)) ===
|
||||
JSON.stringify(['Cat'])
|
||||
);
|
||||
```
|
||||
|
||||
`sliceArray(['Cat', 'Dog', 'Tiger', 'Zebra', 'Ant'], 1, 4)`应返回`['Dog', 'Tiger', 'Zebra']`。
|
||||
|
||||
```js
|
||||
assert(
|
||||
JSON.stringify(sliceArray(['Cat', 'Dog', 'Tiger', 'Zebra', 'Ant'], 1, 4)) ===
|
||||
JSON.stringify(['Dog', 'Tiger', 'Zebra'])
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
---
|
||||
id: 587d7da9367417b2b2512b69
|
||||
title: 使用 sort 方法按字母顺序给数组排序
|
||||
challengeType: 1
|
||||
forumTopicId: 18303
|
||||
title: 使用 sort 方法按字母顺序给数组排序
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
<code>sort</code>方法可以根据回调函数对数组元素进行排序。
|
||||
# --description--
|
||||
|
||||
`sort`方法可以根据回调函数对数组元素进行排序。
|
||||
|
||||
举个例子:
|
||||
|
||||
```js
|
||||
@ -28,67 +29,46 @@ reverseAlpha(['l', 'h', 'z', 'b', 's']);
|
||||
// Returns ['z', 's', 'l', 'h', 'b']
|
||||
```
|
||||
|
||||
JavaScript 的默认排序方法是 Unicode 值顺序排序,有时可能会得到意想不到的结果。所以,建议传入一个回调函数指定数组项目的排序方式,这个回调函数通常叫做 <code>compareFunction</code>,它根据 <code>compareFunction</code> 的返回值决定数组元素的排序方式:
|
||||
如果两个元素 <code>a</code> 和 <code>b</code>,<code>compareFunction(a,b)</code> 返回一个比 0 小的值,那么 <code>a</code> 会在 <code>b</code> 的前面。
|
||||
如果两个元素 <code>a</code> 和 <code>b</code>,<code>compareFunction(a,b)</code> 返回一个比 0 大的值,那么 <code>b</code> 会在 <code>a</code> 的前面。
|
||||
如果两个元素 <code>a</code> 和 <code>b</code>,<code>compareFunction(a,b)</code> 返回等于 0 的值,那么 <code>a</code> 和 <code>b</code> 的位置保持不变。
|
||||
JavaScript 的默认排序方法是 Unicode 值顺序排序,有时可能会得到意想不到的结果。所以,建议传入一个回调函数指定数组项目的排序方式,这个回调函数通常叫做 `compareFunction`,它根据 `compareFunction` 的返回值决定数组元素的排序方式: 如果两个元素 `a` 和 `b`,`compareFunction(a,b)` 返回一个比 0 小的值,那么 `a` 会在 `b` 的前面。 如果两个元素 `a` 和 `b`,`compareFunction(a,b)` 返回一个比 0 大的值,那么 `b` 会在 `a` 的前面。 如果两个元素 `a` 和 `b`,`compareFunction(a,b)` 返回等于 0 的值,那么 `a` 和 `b` 的位置保持不变。
|
||||
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
在<code>alphabeticalOrder</code>函数中使用<code>sort</code>方法对<code>arr</code>中的元素按照字母顺序排列。
|
||||
</section>
|
||||
在`alphabeticalOrder`函数中使用`sort`方法对`arr`中的元素按照字母顺序排列。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 应该使用<code>sort</code>方法。
|
||||
testString: assert(code.match(/\.sort/g));
|
||||
- text: "<code>alphabeticalOrder(['a', 'd', 'c', 'a', 'z', 'g'])</code>应返回<code>['a', 'a', 'c', 'd', 'g', 'z']</code>。"
|
||||
testString: assert(JSON.stringify(alphabeticalOrder(["a", "d", "c", "a", "z", "g"])) === JSON.stringify(["a", "a", "c", "d", "g", "z"]));
|
||||
- text: "<code>alphabeticalOrder(['x', 'h', 'a', 'm', 'n', 'm'])</code>应返回<code>['a', 'h', 'm', 'm', 'n', 'x']</code>。"
|
||||
testString: assert(JSON.stringify(alphabeticalOrder(["x", "h", "a", "m", "n", "m"])) === JSON.stringify(["a", "h", "m", "m", "n", "x"]));
|
||||
- text: "<code>alphabeticalOrder(['a', 'a', 'a', 'a', 'x', 't'])</code>应返回<code>['a', 'a', 'a', 'a', 't', 'x']</code>。"
|
||||
testString: assert(JSON.stringify(alphabeticalOrder(["a", "a", "a", "a", "x", "t"])) === JSON.stringify(["a", "a", "a", "a", "t", "x"]));
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
应该使用`sort`方法。
|
||||
|
||||
```js
|
||||
function alphabeticalOrder(arr) {
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
// Add your code above this line
|
||||
}
|
||||
alphabeticalOrder(["a", "d", "c", "a", "z", "g"]);
|
||||
assert(code.match(/\.sort/g));
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
`alphabeticalOrder(['a', 'd', 'c', 'a', 'z', 'g'])`应返回`['a', 'a', 'c', 'd', 'g', 'z']`。
|
||||
|
||||
```js
|
||||
function alphabeticalOrder(arr) {
|
||||
// Add your code below this line
|
||||
return arr.sort();
|
||||
// Add your code above this line
|
||||
}
|
||||
alphabeticalOrder(["a", "d", "c", "a", "z", "g"]);
|
||||
assert(
|
||||
JSON.stringify(alphabeticalOrder(['a', 'd', 'c', 'a', 'z', 'g'])) ===
|
||||
JSON.stringify(['a', 'a', 'c', 'd', 'g', 'z'])
|
||||
);
|
||||
```
|
||||
|
||||
</section>
|
||||
`alphabeticalOrder(['x', 'h', 'a', 'm', 'n', 'm'])`应返回`['a', 'h', 'm', 'm', 'n', 'x']`。
|
||||
|
||||
```js
|
||||
assert(
|
||||
JSON.stringify(alphabeticalOrder(['x', 'h', 'a', 'm', 'n', 'm'])) ===
|
||||
JSON.stringify(['a', 'h', 'm', 'm', 'n', 'x'])
|
||||
);
|
||||
```
|
||||
|
||||
`alphabeticalOrder(['a', 'a', 'a', 'a', 'x', 't'])`应返回`['a', 'a', 'a', 'a', 't', 'x']`。
|
||||
|
||||
```js
|
||||
assert(
|
||||
JSON.stringify(alphabeticalOrder(['a', 'a', 'a', 'a', 'x', 't'])) ===
|
||||
JSON.stringify(['a', 'a', 'a', 'a', 't', 'x'])
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
---
|
||||
id: 587d7daa367417b2b2512b6b
|
||||
title: 使用 split 方法将字符串拆分成数组
|
||||
challengeType: 1
|
||||
forumTopicId: 18305
|
||||
title: 使用 split 方法将字符串拆分成数组
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
<code>split</code>方法用于把字符串分割成字符串数组,接收一个分隔符参数,分隔符可以是用于分解字符串或正则表达式的字符。举个例子,如果分隔符是空格,你会得到一个单词数组;如果分隔符是空字符串,你会得到一个由字符串中每个字符组成的数组。
|
||||
# --description--
|
||||
|
||||
`split`方法用于把字符串分割成字符串数组,接收一个分隔符参数,分隔符可以是用于分解字符串或正则表达式的字符。举个例子,如果分隔符是空格,你会得到一个单词数组;如果分隔符是空字符串,你会得到一个由字符串中每个字符组成的数组。
|
||||
|
||||
下面是两个用空格分隔一个字符串的例子,另一个是用数字的正则表达式分隔:
|
||||
|
||||
```js
|
||||
@ -20,62 +21,46 @@ var byDigits = otherString.split(/\d/);
|
||||
// Sets byDigits to ["How", "are", "you", "today"]
|
||||
```
|
||||
|
||||
因为字符串是固定的,<code>split</code>方法可以更简单的操作它们。
|
||||
</section>
|
||||
因为字符串是固定的,`split`方法可以更简单的操作它们。
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
在<code>splitify</code>函数中用<code>split</code>方法将<code>str</code>分割成单词数组,这个方法应该返回一个数组。单词不一定都是用空格分隔,所以数组中不应包含标点符号。
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
在`splitify`函数中用`split`方法将`str`分割成单词数组,这个方法应该返回一个数组。单词不一定都是用空格分隔,所以数组中不应包含标点符号。
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 应该使用<code>split</code>方法。
|
||||
testString: assert(code.match(/\.split/g));
|
||||
- text: "<code>splitify('Hello World,I-am code')</code>应返回<code>['Hello', 'World', 'I', 'am', 'code']</code>。"
|
||||
testString: assert(JSON.stringify(splitify("Hello World,I-am code")) === JSON.stringify(["Hello", "World", "I", "am", "code"]));
|
||||
- text: "<code>splitify('Earth-is-our home')</code>应返回<code>['Earth', 'is', 'our', 'home']</code>。"
|
||||
testString: assert(JSON.stringify(splitify("Earth-is-our home")) === JSON.stringify(["Earth", "is", "our", "home"]));
|
||||
- text: "<code>splitify('This.is.a-sentence')</code>应返回<code>['This', 'is', 'a', 'sentence']</code>。"
|
||||
testString: assert(JSON.stringify(splitify("This.is.a-sentence")) === JSON.stringify(["This", "is", "a", "sentence"]));
|
||||
# --hints--
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
应该使用`split`方法。
|
||||
|
||||
```js
|
||||
function splitify(str) {
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
// Add your code above this line
|
||||
}
|
||||
splitify("Hello World,I-am code");
|
||||
assert(code.match(/\.split/g));
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
`splitify('Hello World,I-am code')`应返回`['Hello', 'World', 'I', 'am', 'code']`。
|
||||
|
||||
```js
|
||||
function splitify(str) {
|
||||
// Add your code below this line
|
||||
return str.split(/\W/);
|
||||
// Add your code above this line
|
||||
}
|
||||
assert(
|
||||
JSON.stringify(splitify('Hello World,I-am code')) ===
|
||||
JSON.stringify(['Hello', 'World', 'I', 'am', 'code'])
|
||||
);
|
||||
```
|
||||
|
||||
</section>
|
||||
`splitify('Earth-is-our home')`应返回`['Earth', 'is', 'our', 'home']`。
|
||||
|
||||
```js
|
||||
assert(
|
||||
JSON.stringify(splitify('Earth-is-our home')) ===
|
||||
JSON.stringify(['Earth', 'is', 'our', 'home'])
|
||||
);
|
||||
```
|
||||
|
||||
`splitify('This.is.a-sentence')`应返回`['This', 'is', 'a', 'sentence']`。
|
||||
|
||||
```js
|
||||
assert(
|
||||
JSON.stringify(splitify('This.is.a-sentence')) ===
|
||||
JSON.stringify(['This', 'is', 'a', 'sentence'])
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,119 +1,57 @@
|
||||
---
|
||||
id: 587d7b8e367417b2b2512b5c
|
||||
title: 了解函数式编程术语
|
||||
challengeType: 1
|
||||
forumTopicId: 301240
|
||||
title: 了解函数式编程术语
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
# --description--
|
||||
|
||||
FCC 团队需求有变更,现在想要两种茶:绿茶(green tea)和红茶(black tea)。事实证明,用户需求变更是很常见的。
|
||||
基于以上信息,我们需要重构上一节挑战中的<code>getTea</code>函数来处理多种茶的请求。我们可以修改<code>getTea</code>接受一个函数作为参数,使它能够修改茶的类型。这让<code>getTea</code>更灵活,也使需求变更时为程序员提供更多控制权。
|
||||
|
||||
基于以上信息,我们需要重构上一节挑战中的`getTea`函数来处理多种茶的请求。我们可以修改`getTea`接受一个函数作为参数,使它能够修改茶的类型。这让`getTea`更灵活,也使需求变更时为程序员提供更多控制权。
|
||||
|
||||
首先,我们将介绍一些术语:
|
||||
<code>Callbacks</code>是被传递到另一个函数中调用的函数。你应该已经在其他函数中看过这个写法,例如在<code>filter</code>中,回调函数告诉 JavaScript 以什么规则过滤数组。
|
||||
函数就像其他正常值一样,可以赋值给变量、传递给另一个函数,或从其它函数返回,这种函数叫做<code>头等</code>函数。在 JavaScript 中,所有函数都是<code>头等</code>函数。
|
||||
将函数为参数或返回值的函数叫做<code>高阶</code>函数。
|
||||
当函数传递给另一个函数或从另一个函数返回时,那些传入或返回的函数可以叫做<code>lambda</code>。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
准备 27 杯绿茶和 13 杯红茶,分别存入<code>tea4GreenTeamFCC</code>和<code>tea4BlackTeamFCC</code>变量。请注意,<code>getTea</code>函数已经变了,现在它接收一个函数作为第一个参数。
|
||||
`Callbacks`是被传递到另一个函数中调用的函数。你应该已经在其他函数中看过这个写法,例如在`filter`中,回调函数告诉 JavaScript 以什么规则过滤数组。
|
||||
|
||||
函数就像其他正常值一样,可以赋值给变量、传递给另一个函数,或从其它函数返回,这种函数叫做`头等`函数。在 JavaScript 中,所有函数都是`头等`函数。
|
||||
|
||||
将函数为参数或返回值的函数叫做`高阶`函数。
|
||||
|
||||
当函数传递给另一个函数或从另一个函数返回时,那些传入或返回的函数可以叫做`lambda`。
|
||||
|
||||
# --instructions--
|
||||
|
||||
准备 27 杯绿茶和 13 杯红茶,分别存入`tea4GreenTeamFCC`和`tea4BlackTeamFCC`变量。请注意,`getTea`函数已经变了,现在它接收一个函数作为第一个参数。
|
||||
|
||||
注意:数据(茶的数量)作为最后一个参数。我们将在后面的课程中对此进行更多讨论。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>tea4GreenTeamFCC</code>变量应存有为团队准备的 27 杯茶。
|
||||
testString: assert(tea4GreenTeamFCC.length === 27);
|
||||
- text: <code>tea4GreenTeamFCC</code>变量应存有绿茶。
|
||||
testString: assert(tea4GreenTeamFCC[0] === 'greenTea');
|
||||
- text: <code>tea4BlackTeamFCC</code>变量应存有 13 杯红茶。
|
||||
testString: assert(tea4BlackTeamFCC.length === 13);
|
||||
- text: <code>tea4BlackTeamFCC</code>变量应存有红茶。
|
||||
testString: assert(tea4BlackTeamFCC[0] === 'blackTea');
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
`tea4GreenTeamFCC`变量应存有为团队准备的 27 杯茶。
|
||||
|
||||
```js
|
||||
/**
|
||||
* A long process to prepare green tea.
|
||||
* @return {string} A cup of green tea.
|
||||
**/
|
||||
const prepareGreenTea = () => 'greenTea';
|
||||
|
||||
/**
|
||||
* A long process to prepare black tea.
|
||||
* @return {string} A cup of black tea.
|
||||
**/
|
||||
const prepareBlackTea = () => 'blackTea';
|
||||
|
||||
/**
|
||||
* Get given number of cups of tea.
|
||||
* @param {function():string} prepareTea The type of tea preparing function.
|
||||
* @param {number} numOfCups Number of required cups of tea.
|
||||
* @return {Array<string>} Given amount of tea cups.
|
||||
**/
|
||||
const getTea = (prepareTea, numOfCups) => {
|
||||
const teaCups = [];
|
||||
|
||||
for(let cups = 1; cups <= numOfCups; cups += 1) {
|
||||
const teaCup = prepareTea();
|
||||
teaCups.push(teaCup);
|
||||
}
|
||||
|
||||
return teaCups;
|
||||
};
|
||||
|
||||
// Add your code below this line
|
||||
|
||||
const tea4GreenTeamFCC = null; // :(
|
||||
const tea4BlackTeamFCC = null; // :(
|
||||
|
||||
// Add your code above this line
|
||||
|
||||
console.log(
|
||||
tea4GreenTeamFCC,
|
||||
tea4BlackTeamFCC
|
||||
);
|
||||
assert(tea4GreenTeamFCC.length === 27);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
`tea4GreenTeamFCC`变量应存有绿茶。
|
||||
|
||||
```js
|
||||
// solution required
|
||||
const prepareGreenTea = () => 'greenTea';
|
||||
const prepareBlackTea = () => 'blackTea';
|
||||
|
||||
const getTea = (prepareTea, numOfCups) => {
|
||||
const teaCups = [];
|
||||
|
||||
for(let cups = 1; cups <= numOfCups; cups += 1) {
|
||||
const teaCup = prepareTea();
|
||||
teaCups.push(teaCup);
|
||||
}
|
||||
return teaCups;
|
||||
};
|
||||
|
||||
const tea4BlackTeamFCC = getTea(prepareBlackTea, 13);
|
||||
const tea4GreenTeamFCC = getTea(prepareGreenTea, 27);
|
||||
assert(tea4GreenTeamFCC[0] === 'greenTea');
|
||||
```
|
||||
|
||||
</section>
|
||||
`tea4BlackTeamFCC`变量应存有 13 杯红茶。
|
||||
|
||||
```js
|
||||
assert(tea4BlackTeamFCC.length === 13);
|
||||
```
|
||||
|
||||
`tea4BlackTeamFCC`变量应存有红茶。
|
||||
|
||||
```js
|
||||
assert(tea4BlackTeamFCC[0] === 'blackTea');
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,141 +1,56 @@
|
||||
---
|
||||
id: 587d7b8e367417b2b2512b5d
|
||||
title: 了解使用命令式编程的危害
|
||||
challengeType: 1
|
||||
forumTopicId: 301241
|
||||
title: 了解使用命令式编程的危害
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
# --description--
|
||||
|
||||
函数式编程是一种好习惯,它能让代码管理更简单,不受隐藏 bug 影响。在我们开始函数式编程之前,为了更好的突显可能遇到的问题,我们先看看命令式编程。
|
||||
|
||||
类似在英语(和许多其他语言)中,命令式时态用于给出命令,编程中的命令式是给计算机一组语句来执行任务。
|
||||
这些语句通常会改变程序的状态,例如更新全局变量,典型的例子就是写一个 <code>for</code> 循环,它给出了迭代数组索引的精确方向。
|
||||
|
||||
这些语句通常会改变程序的状态,例如更新全局变量,典型的例子就是写一个 `for` 循环,它给出了迭代数组索引的精确方向。
|
||||
|
||||
相反,函数式编程是声明式编程的一种形式,通过调用方法或函数来告诉计算机要做什么。
|
||||
JavaScript 提供了许多处理常见任务的方法,所以你无需写出计算机应如何执行它们。例如,你可以用 <code>map</code> 函数替代上面提到的 <code>for</code> 循环来处理数组迭代。这有助于避免语义错误,如调试章节介绍的"Off By One Errors"。
|
||||
|
||||
JavaScript 提供了许多处理常见任务的方法,所以你无需写出计算机应如何执行它们。例如,你可以用 `map` 函数替代上面提到的 `for` 循环来处理数组迭代。这有助于避免语义错误,如调试章节介绍的"Off By One Errors"。
|
||||
|
||||
考虑这样的场景:你正在浏览器中浏览网页,并想操作你打开的标签。下面我们来试试用面向对象的思路来描述这种情景。
|
||||
|
||||
窗口对象由选项卡组成,通常会打开多个窗口。窗口对象中每个打开网站的标题都保存在一个数组中。在对浏览器进行了如打开新标签、合并窗口、关闭标签之类的操作后,你需要输出所有打开的标签。关掉的标签将从数组中删除,新打开的标签(为简单起见)则添加到数组的末尾。
|
||||
代码编辑器中显示了此功能的实现,其中包含 <code>tabOpen()</code>,<code>tabClose()</code>,和 <code>join()</code> 函数。tabs数组是窗口对象的一部分用于储存打开页面的名称。
|
||||
|
||||
代码编辑器中显示了此功能的实现,其中包含 `tabOpen()`,`tabClose()`,和 `join()` 函数。tabs数组是窗口对象的一部分用于储存打开页面的名称。
|
||||
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
在编辑器中运行代码。它使用了有副作用的方法,导致输出错误。打开标签的最终列表应该是 `['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium', 'new tab', 'Netflix', 'YouTube', 'Vine', 'GMail', 'Work mail', 'Docs', 'freeCodeCamp', 'new tab']` 但输出会略有不同。
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
在编辑器中运行代码。它使用了有副作用的方法,导致输出错误。打开标签的最终列表应该是 <code>['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium', 'new tab', 'Netflix', 'YouTube', 'Vine', 'GMail', 'Work mail', 'Docs', 'freeCodeCamp', 'new tab']</code> 但输出会略有不同。
|
||||
修改 `Window.prototype.tabClose` 使其删除正确的标签。
|
||||
|
||||
修改 <code>Window.prototype.tabClose</code> 使其删除正确的标签。
|
||||
</section>
|
||||
# --hints--
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>finalTabs.tabs</code> 应该是 <code>['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium', 'new tab', 'Netflix', 'YouTube', 'Vine', 'GMail', 'Work mail', 'Docs', 'freeCodeCamp', 'new tab']</code>
|
||||
testString: assert.deepEqual(finalTabs.tabs, ['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium', 'new tab', 'Netflix', 'YouTube', 'Vine', 'GMail', 'Work mail', 'Docs', 'freeCodeCamp', 'new tab'])
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
`finalTabs.tabs` 应该是 `['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium', 'new tab', 'Netflix', 'YouTube', 'Vine', 'GMail', 'Work mail', 'Docs', 'freeCodeCamp', 'new tab']`
|
||||
|
||||
```js
|
||||
// tabs is an array of titles of each site open within the window
|
||||
var Window = function(tabs) {
|
||||
this.tabs = tabs; // we keep a record of the array inside the object
|
||||
};
|
||||
|
||||
// When you join two windows into one window
|
||||
Window.prototype.join = function (otherWindow) {
|
||||
this.tabs = this.tabs.concat(otherWindow.tabs);
|
||||
return this;
|
||||
};
|
||||
|
||||
// When you open a new tab at the end
|
||||
Window.prototype.tabOpen = function (tab) {
|
||||
this.tabs.push('new tab'); // let's open a new tab for now
|
||||
return this;
|
||||
};
|
||||
|
||||
// When you close a tab
|
||||
Window.prototype.tabClose = function (index) {
|
||||
|
||||
// Only change code below this line
|
||||
|
||||
var tabsBeforeIndex = this.tabs.splice(0, index); // get the tabs before the tab
|
||||
var tabsAfterIndex = this.tabs.splice(index + 1); // get the tabs after the tab
|
||||
|
||||
this.tabs = tabsBeforeIndex.concat(tabsAfterIndex); // join them together
|
||||
|
||||
// Only change code above this line
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
// Let's create three browser windows
|
||||
var workWindow = new Window(['GMail', 'Inbox', 'Work mail', 'Docs', 'freeCodeCamp']); // Your mailbox, drive, and other work sites
|
||||
var socialWindow = new Window(['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium']); // Social sites
|
||||
var videoWindow = new Window(['Netflix', 'YouTube', 'Vimeo', 'Vine']); // Entertainment sites
|
||||
|
||||
// Now perform the tab opening, closing, and other operations
|
||||
var finalTabs = socialWindow
|
||||
.tabOpen() // Open a new tab for cat memes
|
||||
.join(videoWindow.tabClose(2)) // Close third tab in video window, and join
|
||||
.join(workWindow.tabClose(1).tabOpen());
|
||||
console.log(finalTabs.tabs);
|
||||
assert.deepEqual(finalTabs.tabs, [
|
||||
'FB',
|
||||
'Gitter',
|
||||
'Reddit',
|
||||
'Twitter',
|
||||
'Medium',
|
||||
'new tab',
|
||||
'Netflix',
|
||||
'YouTube',
|
||||
'Vine',
|
||||
'GMail',
|
||||
'Work mail',
|
||||
'Docs',
|
||||
'freeCodeCamp',
|
||||
'new tab'
|
||||
]);
|
||||
```
|
||||
|
||||
</div>
|
||||
# --solutions--
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
```js
|
||||
// tabs is an array of titles of each site open within the window
|
||||
var Window = function(tabs) {
|
||||
this.tabs = tabs; // we keep a record of the array inside the object
|
||||
};
|
||||
|
||||
// When you join two windows into one window
|
||||
Window.prototype.join = function (otherWindow) {
|
||||
this.tabs = this.tabs.concat(otherWindow.tabs);
|
||||
return this;
|
||||
};
|
||||
|
||||
// When you open a new tab at the end
|
||||
Window.prototype.tabOpen = function (tab) {
|
||||
this.tabs.push('new tab'); // let's open a new tab for now
|
||||
return this;
|
||||
};
|
||||
|
||||
// When you close a tab
|
||||
Window.prototype.tabClose = function (index) {
|
||||
var tabsBeforeIndex = this.tabs.slice(0, index); // get the tabs before the tab
|
||||
var tabsAfterIndex = this.tabs.slice(index + 1); // get the tabs after the tab
|
||||
|
||||
this.tabs = tabsBeforeIndex.concat(tabsAfterIndex); // join them together
|
||||
return this;
|
||||
};
|
||||
|
||||
// Let's create three browser windows
|
||||
var workWindow = new Window(['GMail', 'Inbox', 'Work mail', 'Docs', 'freeCodeCamp']); // Your mailbox, drive, and other work sites
|
||||
var socialWindow = new Window(['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium']); // Social sites
|
||||
var videoWindow = new Window(['Netflix', 'YouTube', 'Vimeo', 'Vine']); // Entertainment sites
|
||||
|
||||
// Now perform the tab opening, closing, and other operations
|
||||
var finalTabs = socialWindow
|
||||
.tabOpen() // Open a new tab for cat memes
|
||||
.join(videoWindow.tabClose(2)) // Close third tab in video window, and join
|
||||
.join(workWindow.tabClose(1).tabOpen());
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -1,84 +1,66 @@
|
||||
---
|
||||
id: 587d7b88367417b2b2512b45
|
||||
title: 使用高阶函数 map、filter 或者 reduce 来解决复杂问题
|
||||
challengeType: 1
|
||||
forumTopicId: 301311
|
||||
title: 使用高阶函数 map、filter 或者 reduce 来解决复杂问题
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
已经接触了高阶函数如 <code>map()</code>、 <code>filter()</code> 和 <code>reduce()</code>的使用,是时候用它们来完成一些复杂的挑战了。
|
||||
</section>
|
||||
# --description--
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
已经定义了一个函数 <code>squareList</code>。任意组合 <code>map()</code>、<code>filter()</code> 和 <code>reduce()</code> 来完成函数,满足以下条件,当传入实数数组(如,<code>[-3, 4.8, 5, 3, -3.2]</code>)时,返回<em>仅</em>包含正整数的平方的新数组。
|
||||
<strong>注意:</strong> 函数不应该包含任何形式的 <code>for</code> 或者 <code>while</code> 循环或者 <code>forEach()</code> 函数。
|
||||
</section>
|
||||
已经接触了高阶函数如 `map()`、 `filter()` 和 `reduce()`的使用,是时候用它们来完成一些复杂的挑战了。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --instructions--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>squareList</code> 应该是一个 <code>function</code>。
|
||||
testString: assert.typeOf(squareList, 'function'), '<code>squareList</code> should be a <code>function</code>';
|
||||
- text: 不应该使用 for 或者 while 循环或者 forEach。
|
||||
testString: assert(!removeJSComments(code).match(/for|while|forEach/g));
|
||||
- text: 应该使用 <code>map</code>、<code>filter</code> 或者 <code>reduce</code>。
|
||||
testString: assert(removeJSComments(code).match(/\.(map|filter|reduce)\s*\(/g));
|
||||
- text: 函数应该返回 <code>array</code>。
|
||||
testString: assert(Array.isArray(squareList([4, 5.6, -9.8, 3.14, 42, 6, 8.34, -2])));
|
||||
- text: <code>squareList([4, 5.6, -9.8, 3.14, 42, 6, 8.34, -2])</code> 应该返回 <code>[16, 1764, 36]</code>。
|
||||
testString: assert.deepStrictEqual(squareList([4, 5.6, -9.8, 3.14, 42, 6, 8.34, -2]), [16, 1764, 36]);
|
||||
- text: <code>squareList([-3.7, -5, 3, 10, 12.5, 7, -4.5, -17, 0.3])</code> 应该返回 <code>[9, 100, 49]</code>。
|
||||
testString: assert.deepStrictEqual(squareList([-3.7, -5, 3, 10, 12.5, 7, -4.5, -17, 0.3]), [9, 100, 49]);
|
||||
```
|
||||
已经定义了一个函数 `squareList`。任意组合 `map()`、`filter()` 和 `reduce()` 来完成函数,满足以下条件,当传入实数数组(如,`[-3, 4.8, 5, 3, -3.2]`)时,返回*仅*包含正整数的平方的新数组。
|
||||
|
||||
</section>
|
||||
**注意:** 函数不应该包含任何形式的 `for` 或者 `while` 循环或者 `forEach()` 函数。
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
# --hints--
|
||||
|
||||
<div id='js-seed'>
|
||||
`squareList` 应该是一个 `function`。
|
||||
|
||||
```js
|
||||
const squareList = (arr) => {
|
||||
// only change code below this line
|
||||
return arr;
|
||||
// only change code above this line
|
||||
};
|
||||
|
||||
// test your code
|
||||
const squaredIntegers = squareList([-3, 4.8, 5, 3, -3.2]);
|
||||
console.log(squaredIntegers);
|
||||
assert.typeOf(squareList, 'function'),
|
||||
'<code>squareList</code> should be a <code>function</code>';
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<div id='js-teardown'>
|
||||
不应该使用 for 或者 while 循环或者 forEach。
|
||||
|
||||
```js
|
||||
const removeJSComments = str => str.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, '');
|
||||
assert(!removeJSComments(code).match(/for|while|forEach/g));
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
应该使用 `map`、`filter` 或者 `reduce`。
|
||||
|
||||
```js
|
||||
const squareList = (arr) => {
|
||||
const positiveIntegers = arr.filter(num => {
|
||||
return num >= 0 && Number.isInteger(num);
|
||||
});
|
||||
const squaredIntegers = positiveIntegers.map(num => {
|
||||
return num ** 2;
|
||||
});
|
||||
return squaredIntegers;
|
||||
};
|
||||
assert(removeJSComments(code).match(/\.(map|filter|reduce)\s*\(/g));
|
||||
```
|
||||
|
||||
</section>
|
||||
函数应该返回 `array`。
|
||||
|
||||
```js
|
||||
assert(Array.isArray(squareList([4, 5.6, -9.8, 3.14, 42, 6, 8.34, -2])));
|
||||
```
|
||||
|
||||
`squareList([4, 5.6, -9.8, 3.14, 42, 6, 8.34, -2])` 应该返回 `[16, 1764, 36]`。
|
||||
|
||||
```js
|
||||
assert.deepStrictEqual(squareList([4, 5.6, -9.8, 3.14, 42, 6, 8.34, -2]), [
|
||||
16,
|
||||
1764,
|
||||
36
|
||||
]);
|
||||
```
|
||||
|
||||
`squareList([-3.7, -5, 3, 10, 12.5, 7, -4.5, -17, 0.3])` 应该返回 `[9, 100, 49]`。
|
||||
|
||||
```js
|
||||
assert.deepStrictEqual(squareList([-3.7, -5, 3, 10, 12.5, 7, -4.5, -17, 0.3]), [
|
||||
9,
|
||||
100,
|
||||
49
|
||||
]);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,14 +1,15 @@
|
||||
---
|
||||
id: 587d7dab367417b2b2512b6e
|
||||
title: 使用 every 方法检查数组中的每个元素是否符合条件
|
||||
challengeType: 1
|
||||
forumTopicId: 301312
|
||||
title: 使用 every 方法检查数组中的每个元素是否符合条件
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
<code>every</code>方法用于检测数组中<em>所有</em>元素是否都符合指定条件。如果所有元素满足条件,返回布尔值<code>true</code>,反之返回<code>false</code>。
|
||||
举个例子,下面的代码检测数组<code>numbers</code>的所有元素是否都小于 10:
|
||||
# --description--
|
||||
|
||||
`every`方法用于检测数组中*所有*元素是否都符合指定条件。如果所有元素满足条件,返回布尔值`true`,反之返回`false`。
|
||||
|
||||
举个例子,下面的代码检测数组`numbers`的所有元素是否都小于 10:
|
||||
|
||||
```js
|
||||
var numbers = [1, 5, 8, 0, 10, 11];
|
||||
@ -18,62 +19,35 @@ numbers.every(function(currentValue) {
|
||||
// Returns false
|
||||
```
|
||||
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
在<code>checkPositive</code>函数中使用<code>every</code>方法检查<code>arr</code>中是否所有元素都是正数,函数应返回一个布尔值。
|
||||
</section>
|
||||
在`checkPositive`函数中使用`every`方法检查`arr`中是否所有元素都是正数,函数应返回一个布尔值。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 应使用<code>every</code>方法。
|
||||
testString: assert(code.match(/\.every/g));
|
||||
- text: <code>checkPositive([1, 2, 3, -4, 5])</code>应返回<code>false</code>。
|
||||
testString: assert.isFalse(checkPositive([1, 2, 3, -4, 5]));
|
||||
- text: <code>checkPositive([1, 2, 3, 4, 5])</code>应返回<code>true</code>。
|
||||
testString: assert.isTrue(checkPositive([1, 2, 3, 4, 5]));
|
||||
- text: <code>checkPositive([1, -2, 3, -4, 5])</code>应返回<code>false</code>。
|
||||
testString: assert.isFalse(checkPositive([1, -2, 3, -4, 5]));
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
应使用`every`方法。
|
||||
|
||||
```js
|
||||
function checkPositive(arr) {
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
// Add your code above this line
|
||||
}
|
||||
checkPositive([1, 2, 3, -4, 5]);
|
||||
assert(code.match(/\.every/g));
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
`checkPositive([1, 2, 3, -4, 5])`应返回`false`。
|
||||
|
||||
```js
|
||||
function checkPositive(arr) {
|
||||
// Add your code below this line
|
||||
return arr.every(num => num > 0);
|
||||
// Add your code above this line
|
||||
}
|
||||
checkPositive([1, 2, 3, -4, 5]);
|
||||
assert.isFalse(checkPositive([1, 2, 3, -4, 5]));
|
||||
```
|
||||
|
||||
</section>
|
||||
`checkPositive([1, 2, 3, 4, 5])`应返回`true`。
|
||||
|
||||
```js
|
||||
assert.isTrue(checkPositive([1, 2, 3, 4, 5]));
|
||||
```
|
||||
|
||||
`checkPositive([1, -2, 3, -4, 5])`应返回`false`。
|
||||
|
||||
```js
|
||||
assert.isFalse(checkPositive([1, -2, 3, -4, 5]));
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,16 +1,19 @@
|
||||
---
|
||||
id: 587d7b8f367417b2b2512b63
|
||||
title: 使用 filter 方法从数组中提取数据
|
||||
challengeType: 1
|
||||
forumTopicId: 18179
|
||||
title: 使用 filter 方法从数组中提取数据
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
另一个有用的数组方法是<code>filter()</code>(即<code>Array.prototype.filter()</code>)。<code>filter</code>方法会返回一个长度不大于原始数组的新数组。
|
||||
和<code>map</code>一样,<code>Filter</code>不会改变原始数组,它接收一个回调函数,将回调内的逻辑应用于数组的每个元素。新数组包含根据回调函数内条件返回 true 的元素。
|
||||
回调函数接收三个参数。第一个参数是当前正在被处理的元素,第二个参数是元素的索引,第三个参数是在其上调用 <code>filter</code> 方法的数组。
|
||||
看下在 <code>users</code> 上使用 <code>filter</code> 方法的例子,返回了一个新数组包含了 30 岁以下的用户。为了简化,例子里只使用了回调函数的第一个参数。
|
||||
# --description--
|
||||
|
||||
另一个有用的数组方法是`filter()`(即`Array.prototype.filter()`)。`filter`方法会返回一个长度不大于原始数组的新数组。
|
||||
|
||||
和`map`一样,`Filter`不会改变原始数组,它接收一个回调函数,将回调内的逻辑应用于数组的每个元素。新数组包含根据回调函数内条件返回 true 的元素。
|
||||
|
||||
回调函数接收三个参数。第一个参数是当前正在被处理的元素,第二个参数是元素的索引,第三个参数是在其上调用 `filter` 方法的数组。
|
||||
|
||||
看下在 `users` 上使用 `filter` 方法的例子,返回了一个新数组包含了 30 岁以下的用户。为了简化,例子里只使用了回调函数的第一个参数。
|
||||
|
||||
```js
|
||||
const users = [
|
||||
@ -23,287 +26,42 @@ const usersUnder30 = users.filter(user => user.age < 30);
|
||||
console.log(usersUnder30); // [ { name: 'Amy', age: 20 }, { name: 'camperCat', age: 10 } ]
|
||||
```
|
||||
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
<code>watchList</code>是包含一些电影信息的对象。结合<code>filter</code>和<code>map</code>返回一个只包含<code>title</code>和<code>rating</code>属性的新数组,并且<code>imdbRating</code>值大于或等于 8.0。请注意,评级值在对象中保存为字符串,你可能需要将它转换成数字来执行运算。
|
||||
</section>
|
||||
`watchList`是包含一些电影信息的对象。结合`filter`和`map`返回一个只包含`title`和`rating`属性的新数组,并且`imdbRating`值大于或等于 8.0。请注意,评级值在对象中保存为字符串,你可能需要将它转换成数字来执行运算。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>watchList</code>应保持不变。
|
||||
testString: assert(watchList[0].Title === "Inception" && watchList[4].Director == "James Cameron");
|
||||
- text: 应使用<code>filter</code>方法。
|
||||
testString: assert(code.match(/\.filter/g));
|
||||
- text: 不能使用<code>for</code>循环。
|
||||
testString: assert(!code.match(/for\s*?\(.+?\)/g));
|
||||
- text: '<code>filteredList</code>应等于<code>[{"title": "Inception","rating": "8.8"},{"title": "Interstellar","rating": "8.6"},{"title": "The Dark Knight","rating": "9.0"},{"title": "Batman Begins","rating": "8.3"}]</code>。'
|
||||
testString: 'assert.deepEqual(filteredList, [{"title": "Inception","rating": "8.8"},{"title": "Interstellar","rating": "8.6"},{"title": "The Dark Knight","rating": "9.0"},{"title": "Batman Begins","rating": "8.3"}]);'
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
`watchList`应保持不变。
|
||||
|
||||
```js
|
||||
// the global variable
|
||||
var watchList = [
|
||||
{
|
||||
"Title": "Inception",
|
||||
"Year": "2010",
|
||||
"Rated": "PG-13",
|
||||
"Released": "16 Jul 2010",
|
||||
"Runtime": "148 min",
|
||||
"Genre": "Action, Adventure, Crime",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Christopher Nolan",
|
||||
"Actors": "Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy",
|
||||
"Plot": "A thief, who steals corporate secrets through use of dream-sharing technology, is given the inverse task of planting an idea into the mind of a CEO.",
|
||||
"Language": "English, Japanese, French",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 4 Oscars. Another 143 wins & 198 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg",
|
||||
"Metascore": "74",
|
||||
"imdbRating": "8.8",
|
||||
"imdbVotes": "1,446,708",
|
||||
"imdbID": "tt1375666",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Interstellar",
|
||||
"Year": "2014",
|
||||
"Rated": "PG-13",
|
||||
"Released": "07 Nov 2014",
|
||||
"Runtime": "169 min",
|
||||
"Genre": "Adventure, Drama, Sci-Fi",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Jonathan Nolan, Christopher Nolan",
|
||||
"Actors": "Ellen Burstyn, Matthew McConaughey, Mackenzie Foy, John Lithgow",
|
||||
"Plot": "A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.",
|
||||
"Language": "English",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 1 Oscar. Another 39 wins & 132 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMjIxNTU4MzY4MF5BMl5BanBnXkFtZTgwMzM4ODI3MjE@._V1_SX300.jpg",
|
||||
"Metascore": "74",
|
||||
"imdbRating": "8.6",
|
||||
"imdbVotes": "910,366",
|
||||
"imdbID": "tt0816692",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "The Dark Knight",
|
||||
"Year": "2008",
|
||||
"Rated": "PG-13",
|
||||
"Released": "18 Jul 2008",
|
||||
"Runtime": "152 min",
|
||||
"Genre": "Action, Adventure, Crime",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters)",
|
||||
"Actors": "Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine",
|
||||
"Plot": "When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.",
|
||||
"Language": "English, Mandarin",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 2 Oscars. Another 146 wins & 142 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg",
|
||||
"Metascore": "82",
|
||||
"imdbRating": "9.0",
|
||||
"imdbVotes": "1,652,832",
|
||||
"imdbID": "tt0468569",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Batman Begins",
|
||||
"Year": "2005",
|
||||
"Rated": "PG-13",
|
||||
"Released": "15 Jun 2005",
|
||||
"Runtime": "140 min",
|
||||
"Genre": "Action, Adventure",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Bob Kane (characters), David S. Goyer (story), Christopher Nolan (screenplay), David S. Goyer (screenplay)",
|
||||
"Actors": "Christian Bale, Michael Caine, Liam Neeson, Katie Holmes",
|
||||
"Plot": "After training with his mentor, Batman begins his fight to free crime-ridden Gotham City from the corruption that Scarecrow and the League of Shadows have cast upon it.",
|
||||
"Language": "English, Urdu, Mandarin",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Nominated for 1 Oscar. Another 15 wins & 66 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg",
|
||||
"Metascore": "70",
|
||||
"imdbRating": "8.3",
|
||||
"imdbVotes": "972,584",
|
||||
"imdbID": "tt0372784",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Avatar",
|
||||
"Year": "2009",
|
||||
"Rated": "PG-13",
|
||||
"Released": "18 Dec 2009",
|
||||
"Runtime": "162 min",
|
||||
"Genre": "Action, Adventure, Fantasy",
|
||||
"Director": "James Cameron",
|
||||
"Writer": "James Cameron",
|
||||
"Actors": "Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang",
|
||||
"Plot": "A paraplegic marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home.",
|
||||
"Language": "English, Spanish",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 3 Oscars. Another 80 wins & 121 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMTYwOTEwNjAzMl5BMl5BanBnXkFtZTcwODc5MTUwMw@@._V1_SX300.jpg",
|
||||
"Metascore": "83",
|
||||
"imdbRating": "7.9",
|
||||
"imdbVotes": "876,575",
|
||||
"imdbID": "tt0499549",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
}
|
||||
];
|
||||
|
||||
// Add your code below this line
|
||||
|
||||
var filteredList;
|
||||
|
||||
// Add your code above this line
|
||||
|
||||
console.log(filteredList);
|
||||
assert(
|
||||
watchList[0].Title === 'Inception' && watchList[4].Director == 'James Cameron'
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
应使用`filter`方法。
|
||||
|
||||
```js
|
||||
// the global variable
|
||||
var watchList = [
|
||||
{
|
||||
"Title": "Inception",
|
||||
"Year": "2010",
|
||||
"Rated": "PG-13",
|
||||
"Released": "16 Jul 2010",
|
||||
"Runtime": "148 min",
|
||||
"Genre": "Action, Adventure, Crime",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Christopher Nolan",
|
||||
"Actors": "Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy",
|
||||
"Plot": "A thief, who steals corporate secrets through use of dream-sharing technology, is given the inverse task of planting an idea into the mind of a CEO.",
|
||||
"Language": "English, Japanese, French",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 4 Oscars. Another 143 wins & 198 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg",
|
||||
"Metascore": "74",
|
||||
"imdbRating": "8.8",
|
||||
"imdbVotes": "1,446,708",
|
||||
"imdbID": "tt1375666",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Interstellar",
|
||||
"Year": "2014",
|
||||
"Rated": "PG-13",
|
||||
"Released": "07 Nov 2014",
|
||||
"Runtime": "169 min",
|
||||
"Genre": "Adventure, Drama, Sci-Fi",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Jonathan Nolan, Christopher Nolan",
|
||||
"Actors": "Ellen Burstyn, Matthew McConaughey, Mackenzie Foy, John Lithgow",
|
||||
"Plot": "A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.",
|
||||
"Language": "English",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 1 Oscar. Another 39 wins & 132 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMjIxNTU4MzY4MF5BMl5BanBnXkFtZTgwMzM4ODI3MjE@._V1_SX300.jpg",
|
||||
"Metascore": "74",
|
||||
"imdbRating": "8.6",
|
||||
"imdbVotes": "910,366",
|
||||
"imdbID": "tt0816692",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "The Dark Knight",
|
||||
"Year": "2008",
|
||||
"Rated": "PG-13",
|
||||
"Released": "18 Jul 2008",
|
||||
"Runtime": "152 min",
|
||||
"Genre": "Action, Adventure, Crime",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters)",
|
||||
"Actors": "Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine",
|
||||
"Plot": "When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.",
|
||||
"Language": "English, Mandarin",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 2 Oscars. Another 146 wins & 142 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg",
|
||||
"Metascore": "82",
|
||||
"imdbRating": "9.0",
|
||||
"imdbVotes": "1,652,832",
|
||||
"imdbID": "tt0468569",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Batman Begins",
|
||||
"Year": "2005",
|
||||
"Rated": "PG-13",
|
||||
"Released": "15 Jun 2005",
|
||||
"Runtime": "140 min",
|
||||
"Genre": "Action, Adventure",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Bob Kane (characters), David S. Goyer (story), Christopher Nolan (screenplay), David S. Goyer (screenplay)",
|
||||
"Actors": "Christian Bale, Michael Caine, Liam Neeson, Katie Holmes",
|
||||
"Plot": "After training with his mentor, Batman begins his fight to free crime-ridden Gotham City from the corruption that Scarecrow and the League of Shadows have cast upon it.",
|
||||
"Language": "English, Urdu, Mandarin",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Nominated for 1 Oscar. Another 15 wins & 66 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg",
|
||||
"Metascore": "70",
|
||||
"imdbRating": "8.3",
|
||||
"imdbVotes": "972,584",
|
||||
"imdbID": "tt0372784",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Avatar",
|
||||
"Year": "2009",
|
||||
"Rated": "PG-13",
|
||||
"Released": "18 Dec 2009",
|
||||
"Runtime": "162 min",
|
||||
"Genre": "Action, Adventure, Fantasy",
|
||||
"Director": "James Cameron",
|
||||
"Writer": "James Cameron",
|
||||
"Actors": "Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang",
|
||||
"Plot": "A paraplegic marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home.",
|
||||
"Language": "English, Spanish",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 3 Oscars. Another 80 wins & 121 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMTYwOTEwNjAzMl5BMl5BanBnXkFtZTcwODc5MTUwMw@@._V1_SX300.jpg",
|
||||
"Metascore": "83",
|
||||
"imdbRating": "7.9",
|
||||
"imdbVotes": "876,575",
|
||||
"imdbID": "tt0499549",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
}
|
||||
];
|
||||
|
||||
// Add your code below this line
|
||||
let filteredList = watchList.filter(e => e.imdbRating >= 8).map( ({Title: title, imdbRating: rating}) => ({title, rating}) );
|
||||
// Add your code above this line
|
||||
assert(code.match(/\.filter/g));
|
||||
```
|
||||
|
||||
</section>
|
||||
不能使用`for`循环。
|
||||
|
||||
```js
|
||||
assert(!code.match(/for\s*?\(.+?\)/g));
|
||||
```
|
||||
|
||||
`filteredList`应等于`[{"title": "Inception","rating": "8.8"},{"title": "Interstellar","rating": "8.6"},{"title": "The Dark Knight","rating": "9.0"},{"title": "Batman Begins","rating": "8.3"}]`。
|
||||
|
||||
```js
|
||||
assert.deepEqual(filteredList, [
|
||||
{ title: 'Inception', rating: '8.8' },
|
||||
{ title: 'Interstellar', rating: '8.6' },
|
||||
{ title: 'The Dark Knight', rating: '9.0' },
|
||||
{ title: 'Batman Begins', rating: '8.3' }
|
||||
]);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,19 +1,25 @@
|
||||
---
|
||||
id: 587d7b8f367417b2b2512b61
|
||||
title: 使用 map 方法从数组中提取数据
|
||||
challengeType: 1
|
||||
forumTopicId: 18214
|
||||
title: 使用 map 方法从数组中提取数据
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
# --description--
|
||||
|
||||
目前为止,我们已经学会了使用纯函数来避免程序中的副作用。此外,我们已经看到函数的值仅取决于其输入参数。
|
||||
|
||||
这仅仅是个开始。顾名思义,函数式编程以函数理论为中心。
|
||||
能够将它们作为参数传递给其他函数,和从另一个函数返回一个函数是有意义的。函数在 JavaScript 中被视为<code>First Class Objects</code>,它们可以像任何其他对象一样使用。它们可以保存在变量中,存储在对象中,也可以作为函数参数传递。
|
||||
让我们从一些简单的数组函数开始,这些函数是数组对象原型上的方法。在本练习中,我们来了解下数组的<code>map</code>方法(即<code>Array.prototype.map()</code>)。
|
||||
请记住,<code>map</code>方法是迭代数组中每一项的方式之一。在对每个元素应用回调函数后,它会创建一个新数组(不改变原来的数组)。
|
||||
当调用回调函数时,传入了三个参数。第一个参数是当前正在处理的数组项,第二个参数是当前数组项的索引值,第三个参数是在其上调用 <code>map</code> 方法的数组。
|
||||
看下在 <code>users</code> 上使用 <code>map</code> 方法的例子,返回了一个新数组只包含了用户的名字。为了简化,例子里只使用了回调函数的第一个参数。
|
||||
|
||||
能够将它们作为参数传递给其他函数,和从另一个函数返回一个函数是有意义的。函数在 JavaScript 中被视为`First Class Objects`,它们可以像任何其他对象一样使用。它们可以保存在变量中,存储在对象中,也可以作为函数参数传递。
|
||||
|
||||
让我们从一些简单的数组函数开始,这些函数是数组对象原型上的方法。在本练习中,我们来了解下数组的`map`方法(即`Array.prototype.map()`)。
|
||||
|
||||
请记住,`map`方法是迭代数组中每一项的方式之一。在对每个元素应用回调函数后,它会创建一个新数组(不改变原来的数组)。
|
||||
|
||||
当调用回调函数时,传入了三个参数。第一个参数是当前正在处理的数组项,第二个参数是当前数组项的索引值,第三个参数是在其上调用 `map` 方法的数组。
|
||||
|
||||
看下在 `users` 上使用 `map` 方法的例子,返回了一个新数组只包含了用户的名字。为了简化,例子里只使用了回调函数的第一个参数。
|
||||
|
||||
```js
|
||||
const users = [
|
||||
@ -26,300 +32,46 @@ const names = users.map(user => user.name);
|
||||
console.log(names); // [ 'John', 'Amy', 'camperCat' ]
|
||||
```
|
||||
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
<code>watchList</code>数组保存了包含一些电影信息的对象。使用<code>map</code>从<code>watchList</code>中提取标题(<code>title</code>)和评分(<code>rating</code>),并将新数组保存在<code>rating</code>变量里。目前编辑器中的代码是使用<code>for</code>循环实现,使用<code>map</code>表达式替换循环功能。
|
||||
</section>
|
||||
`watchList`数组保存了包含一些电影信息的对象。使用`map`从`watchList`中提取标题(`title`)和评分(`rating`),并将新数组保存在`rating`变量里。目前编辑器中的代码是使用`for`循环实现,使用`map`表达式替换循环功能。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>watchList</code>不能被改变
|
||||
testString: assert(watchList[0].Title === "Inception" && watchList[4].Director == "James Cameron");
|
||||
- text: 你的代码不能使用<code>for</code>循环。
|
||||
testString: assert(!removeJSComments(code).match(/for\s*?\(.*?\)/));
|
||||
- text: 你的代码应使用<code>map</code>方法。
|
||||
testString: assert(code.match(/\.map/g));
|
||||
- text: '<code>rating</code>应等于<code>[{"title":"Inception","rating":"8.8"},{"title":"Interstellar","rating":"8.6"},{"title":"The Dark Knight","rating":"9.0"},{"title":"Batman Begins","rating":"8.3"},{"title":"Avatar","rating":"7.9"}]</code>.'
|
||||
testString: assert(JSON.stringify(ratings) === JSON.stringify([{"title":"Inception","rating":"8.8"},{"title":"Interstellar","rating":"8.6"},{"title":"The Dark Knight","rating":"9.0"},{"title":"Batman Begins","rating":"8.3"},{"title":"Avatar","rating":"7.9"}]));
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
`watchList`不能被改变
|
||||
|
||||
```js
|
||||
// the global variable
|
||||
var watchList = [
|
||||
{
|
||||
"Title": "Inception",
|
||||
"Year": "2010",
|
||||
"Rated": "PG-13",
|
||||
"Released": "16 Jul 2010",
|
||||
"Runtime": "148 min",
|
||||
"Genre": "Action, Adventure, Crime",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Christopher Nolan",
|
||||
"Actors": "Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy",
|
||||
"Plot": "A thief, who steals corporate secrets through use of dream-sharing technology, is given the inverse task of planting an idea into the mind of a CEO.",
|
||||
"Language": "English, Japanese, French",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 4 Oscars. Another 143 wins & 198 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg",
|
||||
"Metascore": "74",
|
||||
"imdbRating": "8.8",
|
||||
"imdbVotes": "1,446,708",
|
||||
"imdbID": "tt1375666",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Interstellar",
|
||||
"Year": "2014",
|
||||
"Rated": "PG-13",
|
||||
"Released": "07 Nov 2014",
|
||||
"Runtime": "169 min",
|
||||
"Genre": "Adventure, Drama, Sci-Fi",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Jonathan Nolan, Christopher Nolan",
|
||||
"Actors": "Ellen Burstyn, Matthew McConaughey, Mackenzie Foy, John Lithgow",
|
||||
"Plot": "A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.",
|
||||
"Language": "English",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 1 Oscar. Another 39 wins & 132 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMjIxNTU4MzY4MF5BMl5BanBnXkFtZTgwMzM4ODI3MjE@._V1_SX300.jpg",
|
||||
"Metascore": "74",
|
||||
"imdbRating": "8.6",
|
||||
"imdbVotes": "910,366",
|
||||
"imdbID": "tt0816692",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "The Dark Knight",
|
||||
"Year": "2008",
|
||||
"Rated": "PG-13",
|
||||
"Released": "18 Jul 2008",
|
||||
"Runtime": "152 min",
|
||||
"Genre": "Action, Adventure, Crime",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters)",
|
||||
"Actors": "Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine",
|
||||
"Plot": "When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.",
|
||||
"Language": "English, Mandarin",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 2 Oscars. Another 146 wins & 142 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg",
|
||||
"Metascore": "82",
|
||||
"imdbRating": "9.0",
|
||||
"imdbVotes": "1,652,832",
|
||||
"imdbID": "tt0468569",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Batman Begins",
|
||||
"Year": "2005",
|
||||
"Rated": "PG-13",
|
||||
"Released": "15 Jun 2005",
|
||||
"Runtime": "140 min",
|
||||
"Genre": "Action, Adventure",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Bob Kane (characters), David S. Goyer (story), Christopher Nolan (screenplay), David S. Goyer (screenplay)",
|
||||
"Actors": "Christian Bale, Michael Caine, Liam Neeson, Katie Holmes",
|
||||
"Plot": "After training with his mentor, Batman begins his fight to free crime-ridden Gotham City from the corruption that Scarecrow and the League of Shadows have cast upon it.",
|
||||
"Language": "English, Urdu, Mandarin",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Nominated for 1 Oscar. Another 15 wins & 66 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg",
|
||||
"Metascore": "70",
|
||||
"imdbRating": "8.3",
|
||||
"imdbVotes": "972,584",
|
||||
"imdbID": "tt0372784",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Avatar",
|
||||
"Year": "2009",
|
||||
"Rated": "PG-13",
|
||||
"Released": "18 Dec 2009",
|
||||
"Runtime": "162 min",
|
||||
"Genre": "Action, Adventure, Fantasy",
|
||||
"Director": "James Cameron",
|
||||
"Writer": "James Cameron",
|
||||
"Actors": "Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang",
|
||||
"Plot": "A paraplegic marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home.",
|
||||
"Language": "English, Spanish",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 3 Oscars. Another 80 wins & 121 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMTYwOTEwNjAzMl5BMl5BanBnXkFtZTcwODc5MTUwMw@@._V1_SX300.jpg",
|
||||
"Metascore": "83",
|
||||
"imdbRating": "7.9",
|
||||
"imdbVotes": "876,575",
|
||||
"imdbID": "tt0499549",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
}
|
||||
];
|
||||
|
||||
// Add your code below this line
|
||||
|
||||
var ratings = [];
|
||||
for(var i=0; i < watchList.length; i++){
|
||||
ratings.push({title: watchList[i]["Title"], rating: watchList[i]["imdbRating"]});
|
||||
}
|
||||
|
||||
// Add your code above this line
|
||||
|
||||
console.log(JSON.stringify(ratings));
|
||||
assert(
|
||||
watchList[0].Title === 'Inception' && watchList[4].Director == 'James Cameron'
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
### After Test
|
||||
<div id='js-teardown'>
|
||||
你的代码不能使用`for`循环。
|
||||
|
||||
```js
|
||||
const removeJSComments = str => str.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, '');
|
||||
assert(!removeJSComments(code).match(/for\s*?\(.*?\)/));
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
你的代码应使用`map`方法。
|
||||
|
||||
```js
|
||||
// the global variable
|
||||
var watchList = [
|
||||
{
|
||||
"Title": "Inception",
|
||||
"Year": "2010",
|
||||
"Rated": "PG-13",
|
||||
"Released": "16 Jul 2010",
|
||||
"Runtime": "148 min",
|
||||
"Genre": "Action, Adventure, Crime",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Christopher Nolan",
|
||||
"Actors": "Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy",
|
||||
"Plot": "A thief, who steals corporate secrets through use of dream-sharing technology, is given the inverse task of planting an idea into the mind of a CEO.",
|
||||
"Language": "English, Japanese, French",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 4 Oscars. Another 143 wins & 198 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg",
|
||||
"Metascore": "74",
|
||||
"imdbRating": "8.8",
|
||||
"imdbVotes": "1,446,708",
|
||||
"imdbID": "tt1375666",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Interstellar",
|
||||
"Year": "2014",
|
||||
"Rated": "PG-13",
|
||||
"Released": "07 Nov 2014",
|
||||
"Runtime": "169 min",
|
||||
"Genre": "Adventure, Drama, Sci-Fi",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Jonathan Nolan, Christopher Nolan",
|
||||
"Actors": "Ellen Burstyn, Matthew McConaughey, Mackenzie Foy, John Lithgow",
|
||||
"Plot": "A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.",
|
||||
"Language": "English",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 1 Oscar. Another 39 wins & 132 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMjIxNTU4MzY4MF5BMl5BanBnXkFtZTgwMzM4ODI3MjE@._V1_SX300.jpg",
|
||||
"Metascore": "74",
|
||||
"imdbRating": "8.6",
|
||||
"imdbVotes": "910,366",
|
||||
"imdbID": "tt0816692",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "The Dark Knight",
|
||||
"Year": "2008",
|
||||
"Rated": "PG-13",
|
||||
"Released": "18 Jul 2008",
|
||||
"Runtime": "152 min",
|
||||
"Genre": "Action, Adventure, Crime",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters)",
|
||||
"Actors": "Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine",
|
||||
"Plot": "When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.",
|
||||
"Language": "English, Mandarin",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 2 Oscars. Another 146 wins & 142 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg",
|
||||
"Metascore": "82",
|
||||
"imdbRating": "9.0",
|
||||
"imdbVotes": "1,652,832",
|
||||
"imdbID": "tt0468569",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Batman Begins",
|
||||
"Year": "2005",
|
||||
"Rated": "PG-13",
|
||||
"Released": "15 Jun 2005",
|
||||
"Runtime": "140 min",
|
||||
"Genre": "Action, Adventure",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Bob Kane (characters), David S. Goyer (story), Christopher Nolan (screenplay), David S. Goyer (screenplay)",
|
||||
"Actors": "Christian Bale, Michael Caine, Liam Neeson, Katie Holmes",
|
||||
"Plot": "After training with his mentor, Batman begins his fight to free crime-ridden Gotham City from the corruption that Scarecrow and the League of Shadows have cast upon it.",
|
||||
"Language": "English, Urdu, Mandarin",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Nominated for 1 Oscar. Another 15 wins & 66 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg",
|
||||
"Metascore": "70",
|
||||
"imdbRating": "8.3",
|
||||
"imdbVotes": "972,584",
|
||||
"imdbID": "tt0372784",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Avatar",
|
||||
"Year": "2009",
|
||||
"Rated": "PG-13",
|
||||
"Released": "18 Dec 2009",
|
||||
"Runtime": "162 min",
|
||||
"Genre": "Action, Adventure, Fantasy",
|
||||
"Director": "James Cameron",
|
||||
"Writer": "James Cameron",
|
||||
"Actors": "Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang",
|
||||
"Plot": "A paraplegic marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home.",
|
||||
"Language": "English, Spanish",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 3 Oscars. Another 80 wins & 121 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMTYwOTEwNjAzMl5BMl5BanBnXkFtZTcwODc5MTUwMw@@._V1_SX300.jpg",
|
||||
"Metascore": "83",
|
||||
"imdbRating": "7.9",
|
||||
"imdbVotes": "876,575",
|
||||
"imdbID": "tt0499549",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
}
|
||||
];
|
||||
|
||||
var ratings = watchList.map(function(movie) {
|
||||
return {
|
||||
title: movie["Title"],
|
||||
rating: movie["imdbRating"]
|
||||
}
|
||||
});
|
||||
assert(code.match(/\.map/g));
|
||||
```
|
||||
|
||||
</section>
|
||||
`rating`应等于`[{"title":"Inception","rating":"8.8"},{"title":"Interstellar","rating":"8.6"},{"title":"The Dark Knight","rating":"9.0"},{"title":"Batman Begins","rating":"8.3"},{"title":"Avatar","rating":"7.9"}]`.
|
||||
|
||||
```js
|
||||
assert(
|
||||
JSON.stringify(ratings) ===
|
||||
JSON.stringify([
|
||||
{ title: 'Inception', rating: '8.8' },
|
||||
{ title: 'Interstellar', rating: '8.6' },
|
||||
{ title: 'The Dark Knight', rating: '9.0' },
|
||||
{ title: 'Batman Begins', rating: '8.3' },
|
||||
{ title: 'Avatar', rating: '7.9' }
|
||||
])
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,23 +1,21 @@
|
||||
---
|
||||
id: 587d7da9367417b2b2512b68
|
||||
title: 使用 reduce 方法分析数据
|
||||
challengeType: 1
|
||||
forumTopicId: 301313
|
||||
title: 使用 reduce 方法分析数据
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
# --description--
|
||||
|
||||
<code>reduce()</code>(即<code>Array.prototype.reduce()</code>),是 JavaScript 所有数组操作中最常用的方法。几乎可以用<code>reduce</code>方法解决所有数组处理问题。
|
||||
`reduce()`(即`Array.prototype.reduce()`),是 JavaScript 所有数组操作中最常用的方法。几乎可以用`reduce`方法解决所有数组处理问题。
|
||||
|
||||
<code>reduce</code>方法是处理数组更通用的方式,而且<code>filter</code>和<code>map</code>方法都可以当作是<code>reduce</code>的特殊实现。
|
||||
<code> reduce </code>方法遍历数组中的每个项目并返回单个值(即字符串、数字、对象、数组)。 这是通过在每次迭代中调用一个回调函数来实现的。
|
||||
`reduce`方法是处理数组更通用的方式,而且`filter`和`map`方法都可以当作是`reduce`的特殊实现。 `reduce`方法遍历数组中的每个项目并返回单个值(即字符串、数字、对象、数组)。 这是通过在每次迭代中调用一个回调函数来实现的。
|
||||
|
||||
回调函数接受四个参数。第一个参数称为叠加器,它是上一次迭代中回调函数的返回值,第二个参数是当前正在处理的数组元素,第三个参数是该参数的索引,第四个参数是在其上调用 <code>reduce</code> 方法的数组。
|
||||
回调函数接受四个参数。第一个参数称为叠加器,它是上一次迭代中回调函数的返回值,第二个参数是当前正在处理的数组元素,第三个参数是该参数的索引,第四个参数是在其上调用 `reduce` 方法的数组。
|
||||
|
||||
除了回调函数,<code>reduce</code> 还有一个额外的参数做为叠加器的初始值。如果没有第二个参数,会跳过第一次迭代,第二次迭代给叠加器传入数组的第一个元素。
|
||||
除了回调函数,`reduce` 还有一个额外的参数做为叠加器的初始值。如果没有第二个参数,会跳过第一次迭代,第二次迭代给叠加器传入数组的第一个元素。
|
||||
|
||||
见下面的例子,给 <code>users</code> 数组使用 <code>reduce</code> 方法,返回所有用户数组的和。为了简化,例子仅使用了回调函数的第一个参数和第二个参数。
|
||||
见下面的例子,给 `users` 数组使用 `reduce` 方法,返回所有用户数组的和。为了简化,例子仅使用了回调函数的第一个参数和第二个参数。
|
||||
|
||||
```js
|
||||
const users = [
|
||||
@ -46,297 +44,43 @@ const usersObj = users.reduce((obj, user) => {
|
||||
console.log(usersObj); // { John: 34, Amy: 20, camperCat: 10 }
|
||||
```
|
||||
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
<code>watchList</code>变量中包含一组存有多部电影信息对象。使用<code>reduce</code>查找由<strong> Christopher Nolan 导演</strong>的电影的 IMDB 评级平均值。回想一下之前的挑战,如何<code>filter</code>数据,以及使用<code>map</code>来获取你想要的数据。你可能需要创建一些变量,但是请将最后的平均值保存到<code>averageRating</code>变量中。请注意,评级在对象中是字符串,需要将其转换为数字再用于数学运算。
|
||||
</section>
|
||||
`watchList`变量中包含一组存有多部电影信息对象。使用`reduce`查找由**Christopher Nolan 导演**的电影的 IMDB 评级平均值。回想一下之前的挑战,如何`filter`数据,以及使用`map`来获取你想要的数据。你可能需要创建一些变量,但是请将最后的平均值保存到`averageRating`变量中。请注意,评级在对象中是字符串,需要将其转换为数字再用于数学运算。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>watchList</code>应保持不变。
|
||||
testString: assert(watchList[0].Title === "Inception" && watchList[4].Director == "James Cameron");
|
||||
- text: 应该使用<code>reduce</code>方法。
|
||||
testString: assert(code.match(/\.reduce/g));
|
||||
- text: The<code>averageRating</code>应等于 8.675。
|
||||
testString: assert(getRating(watchList) === 8.675);
|
||||
- text: 不能使用<code>for</code>循环。
|
||||
testString: assert(!code.match(/for\s*?\(.*\)/g));
|
||||
- text: 在修改 <code>watchList</code> 对象后应该返回正确的输出。
|
||||
testString: assert(getRating(watchList.filter((_, i) => i < 1 || i > 2)) === 8.55);
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
`watchList`应保持不变。
|
||||
|
||||
```js
|
||||
// the global variable
|
||||
var watchList = [
|
||||
{
|
||||
"Title": "Inception",
|
||||
"Year": "2010",
|
||||
"Rated": "PG-13",
|
||||
"Released": "16 Jul 2010",
|
||||
"Runtime": "148 min",
|
||||
"Genre": "Action, Adventure, Crime",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Christopher Nolan",
|
||||
"Actors": "Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy",
|
||||
"Plot": "A thief, who steals corporate secrets through use of dream-sharing technology, is given the inverse task of planting an idea into the mind of a CEO.",
|
||||
"Language": "English, Japanese, French",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 4 Oscars. Another 143 wins & 198 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg",
|
||||
"Metascore": "74",
|
||||
"imdbRating": "8.8",
|
||||
"imdbVotes": "1,446,708",
|
||||
"imdbID": "tt1375666",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Interstellar",
|
||||
"Year": "2014",
|
||||
"Rated": "PG-13",
|
||||
"Released": "07 Nov 2014",
|
||||
"Runtime": "169 min",
|
||||
"Genre": "Adventure, Drama, Sci-Fi",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Jonathan Nolan, Christopher Nolan",
|
||||
"Actors": "Ellen Burstyn, Matthew McConaughey, Mackenzie Foy, John Lithgow",
|
||||
"Plot": "A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.",
|
||||
"Language": "English",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 1 Oscar. Another 39 wins & 132 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMjIxNTU4MzY4MF5BMl5BanBnXkFtZTgwMzM4ODI3MjE@._V1_SX300.jpg",
|
||||
"Metascore": "74",
|
||||
"imdbRating": "8.6",
|
||||
"imdbVotes": "910,366",
|
||||
"imdbID": "tt0816692",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "The Dark Knight",
|
||||
"Year": "2008",
|
||||
"Rated": "PG-13",
|
||||
"Released": "18 Jul 2008",
|
||||
"Runtime": "152 min",
|
||||
"Genre": "Action, Adventure, Crime",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters)",
|
||||
"Actors": "Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine",
|
||||
"Plot": "When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.",
|
||||
"Language": "English, Mandarin",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 2 Oscars. Another 146 wins & 142 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg",
|
||||
"Metascore": "82",
|
||||
"imdbRating": "9.0",
|
||||
"imdbVotes": "1,652,832",
|
||||
"imdbID": "tt0468569",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Batman Begins",
|
||||
"Year": "2005",
|
||||
"Rated": "PG-13",
|
||||
"Released": "15 Jun 2005",
|
||||
"Runtime": "140 min",
|
||||
"Genre": "Action, Adventure",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Bob Kane (characters), David S. Goyer (story), Christopher Nolan (screenplay), David S. Goyer (screenplay)",
|
||||
"Actors": "Christian Bale, Michael Caine, Liam Neeson, Katie Holmes",
|
||||
"Plot": "After training with his mentor, Batman begins his fight to free crime-ridden Gotham City from the corruption that Scarecrow and the League of Shadows have cast upon it.",
|
||||
"Language": "English, Urdu, Mandarin",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Nominated for 1 Oscar. Another 15 wins & 66 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg",
|
||||
"Metascore": "70",
|
||||
"imdbRating": "8.3",
|
||||
"imdbVotes": "972,584",
|
||||
"imdbID": "tt0372784",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Avatar",
|
||||
"Year": "2009",
|
||||
"Rated": "PG-13",
|
||||
"Released": "18 Dec 2009",
|
||||
"Runtime": "162 min",
|
||||
"Genre": "Action, Adventure, Fantasy",
|
||||
"Director": "James Cameron",
|
||||
"Writer": "James Cameron",
|
||||
"Actors": "Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang",
|
||||
"Plot": "A paraplegic marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home.",
|
||||
"Language": "English, Spanish",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 3 Oscars. Another 80 wins & 121 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMTYwOTEwNjAzMl5BMl5BanBnXkFtZTcwODc5MTUwMw@@._V1_SX300.jpg",
|
||||
"Metascore": "83",
|
||||
"imdbRating": "7.9",
|
||||
"imdbVotes": "876,575",
|
||||
"imdbID": "tt0499549",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
}
|
||||
];
|
||||
|
||||
function getRating(watchList){
|
||||
// Add your code below this line
|
||||
var averageRating;
|
||||
|
||||
|
||||
// Add your code above this line
|
||||
return averageRating;
|
||||
}
|
||||
console.log(getRating(watchList));
|
||||
assert(
|
||||
watchList[0].Title === 'Inception' && watchList[4].Director == 'James Cameron'
|
||||
);
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
应该使用`reduce`方法。
|
||||
|
||||
```js
|
||||
// the global variable
|
||||
var watchList = [
|
||||
{
|
||||
"Title": "Inception",
|
||||
"Year": "2010",
|
||||
"Rated": "PG-13",
|
||||
"Released": "16 Jul 2010",
|
||||
"Runtime": "148 min",
|
||||
"Genre": "Action, Adventure, Crime",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Christopher Nolan",
|
||||
"Actors": "Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy",
|
||||
"Plot": "A thief, who steals corporate secrets through use of dream-sharing technology, is given the inverse task of planting an idea into the mind of a CEO.",
|
||||
"Language": "English, Japanese, French",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 4 Oscars. Another 143 wins & 198 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg",
|
||||
"Metascore": "74",
|
||||
"imdbRating": "8.8",
|
||||
"imdbVotes": "1,446,708",
|
||||
"imdbID": "tt1375666",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Interstellar",
|
||||
"Year": "2014",
|
||||
"Rated": "PG-13",
|
||||
"Released": "07 Nov 2014",
|
||||
"Runtime": "169 min",
|
||||
"Genre": "Adventure, Drama, Sci-Fi",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Jonathan Nolan, Christopher Nolan",
|
||||
"Actors": "Ellen Burstyn, Matthew McConaughey, Mackenzie Foy, John Lithgow",
|
||||
"Plot": "A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.",
|
||||
"Language": "English",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 1 Oscar. Another 39 wins & 132 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMjIxNTU4MzY4MF5BMl5BanBnXkFtZTgwMzM4ODI3MjE@._V1_SX300.jpg",
|
||||
"Metascore": "74",
|
||||
"imdbRating": "8.6",
|
||||
"imdbVotes": "910,366",
|
||||
"imdbID": "tt0816692",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "The Dark Knight",
|
||||
"Year": "2008",
|
||||
"Rated": "PG-13",
|
||||
"Released": "18 Jul 2008",
|
||||
"Runtime": "152 min",
|
||||
"Genre": "Action, Adventure, Crime",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters)",
|
||||
"Actors": "Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine",
|
||||
"Plot": "When the menace known as the Joker wreaks havoc and chaos on the people of Gotham, the caped crusader must come to terms with one of the greatest psychological tests of his ability to fight injustice.",
|
||||
"Language": "English, Mandarin",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 2 Oscars. Another 146 wins & 142 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg",
|
||||
"Metascore": "82",
|
||||
"imdbRating": "9.0",
|
||||
"imdbVotes": "1,652,832",
|
||||
"imdbID": "tt0468569",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Batman Begins",
|
||||
"Year": "2005",
|
||||
"Rated": "PG-13",
|
||||
"Released": "15 Jun 2005",
|
||||
"Runtime": "140 min",
|
||||
"Genre": "Action, Adventure",
|
||||
"Director": "Christopher Nolan",
|
||||
"Writer": "Bob Kane (characters), David S. Goyer (story), Christopher Nolan (screenplay), David S. Goyer (screenplay)",
|
||||
"Actors": "Christian Bale, Michael Caine, Liam Neeson, Katie Holmes",
|
||||
"Plot": "After training with his mentor, Batman begins his fight to free crime-ridden Gotham City from the corruption that Scarecrow and the League of Shadows have cast upon it.",
|
||||
"Language": "English, Urdu, Mandarin",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Nominated for 1 Oscar. Another 15 wins & 66 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg",
|
||||
"Metascore": "70",
|
||||
"imdbRating": "8.3",
|
||||
"imdbVotes": "972,584",
|
||||
"imdbID": "tt0372784",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
},
|
||||
{
|
||||
"Title": "Avatar",
|
||||
"Year": "2009",
|
||||
"Rated": "PG-13",
|
||||
"Released": "18 Dec 2009",
|
||||
"Runtime": "162 min",
|
||||
"Genre": "Action, Adventure, Fantasy",
|
||||
"Director": "James Cameron",
|
||||
"Writer": "James Cameron",
|
||||
"Actors": "Sam Worthington, Zoe Saldana, Sigourney Weaver, Stephen Lang",
|
||||
"Plot": "A paraplegic marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home.",
|
||||
"Language": "English, Spanish",
|
||||
"Country": "USA, UK",
|
||||
"Awards": "Won 3 Oscars. Another 80 wins & 121 nominations.",
|
||||
"Poster": "http://ia.media-imdb.com/images/M/MV5BMTYwOTEwNjAzMl5BMl5BanBnXkFtZTcwODc5MTUwMw@@._V1_SX300.jpg",
|
||||
"Metascore": "83",
|
||||
"imdbRating": "7.9",
|
||||
"imdbVotes": "876,575",
|
||||
"imdbID": "tt0499549",
|
||||
"Type": "movie",
|
||||
"Response": "True"
|
||||
}
|
||||
];
|
||||
|
||||
function getRating(watchList){
|
||||
var averageRating;
|
||||
const rating = watchList
|
||||
.filter(obj => obj.Director === "Christopher Nolan")
|
||||
.map(obj => Number(obj.imdbRating));
|
||||
averageRating = rating.reduce((accum, curr) => accum + curr)/rating.length;
|
||||
return averageRating;
|
||||
}
|
||||
|
||||
assert(code.match(/\.reduce/g));
|
||||
```
|
||||
|
||||
</section>
|
||||
The`averageRating`应等于 8.675。
|
||||
|
||||
```js
|
||||
assert(getRating(watchList) === 8.675);
|
||||
```
|
||||
|
||||
不能使用`for`循环。
|
||||
|
||||
```js
|
||||
assert(!code.match(/for\s*?\(.*\)/g));
|
||||
```
|
||||
|
||||
在修改 `watchList` 对象后应该返回正确的输出。
|
||||
|
||||
```js
|
||||
assert(getRating(watchList.filter((_, i) => i < 1 || i > 2)) === 8.55);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
@ -1,14 +1,15 @@
|
||||
---
|
||||
id: 587d7dab367417b2b2512b6f
|
||||
title: 使用 some 方法检查数组中是否有元素是否符合条件
|
||||
challengeType: 1
|
||||
forumTopicId: 301314
|
||||
title: 使用 some 方法检查数组中是否有元素是否符合条件
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id='description'>
|
||||
<code>some</code>方法用于检测数组中<em>任何</em>元素是否满足指定条件。如果有一个元素满足条件,返回布尔值<code>true</code>,反之返回<code>false</code>。
|
||||
举个例子,下面的代码检测数组<code>numbers</code>中是否有元素小于10:
|
||||
# --description--
|
||||
|
||||
`some`方法用于检测数组中*任何*元素是否满足指定条件。如果有一个元素满足条件,返回布尔值`true`,反之返回`false`。
|
||||
|
||||
举个例子,下面的代码检测数组`numbers`中是否有元素小于10:
|
||||
|
||||
```js
|
||||
var numbers = [10, 50, 8, 220, 110, 11];
|
||||
@ -18,62 +19,35 @@ numbers.some(function(currentValue) {
|
||||
// Returns true
|
||||
```
|
||||
|
||||
</section>
|
||||
# --instructions--
|
||||
|
||||
## Instructions
|
||||
<section id='instructions'>
|
||||
在<code>checkPositive</code>函数值中使用<code>some</code>检查<code>arr</code>中是否有元素为正数,函数应返回一个布尔值。
|
||||
</section>
|
||||
在`checkPositive`函数值中使用`some`检查`arr`中是否有元素为正数,函数应返回一个布尔值。
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
# --hints--
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 应该使用<code>some</code>method.
|
||||
testString: assert(code.match(/\.some/g));
|
||||
- text: <code>checkPositive([1, 2, 3, -4, 5])</code>应返回<code>true</code>。
|
||||
testString: assert(checkPositive([1, 2, 3, -4, 5]));
|
||||
- text: <code>checkPositive([1, 2, 3, 4, 5])</code>应返回<code>true</code>。
|
||||
testString: assert(checkPositive([1, 2, 3, 4, 5]));
|
||||
- text: <code>checkPositive([-1, -2, -3, -4, -5])</code>应返回<code>false</code>。
|
||||
testString: assert(!checkPositive([-1, -2, -3, -4, -5]));
|
||||
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Challenge Seed
|
||||
<section id='challengeSeed'>
|
||||
|
||||
<div id='js-seed'>
|
||||
应该使用`some`method.
|
||||
|
||||
```js
|
||||
function checkPositive(arr) {
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
// Add your code above this line
|
||||
}
|
||||
checkPositive([1, 2, 3, -4, 5]);
|
||||
assert(code.match(/\.some/g));
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
`checkPositive([1, 2, 3, -4, 5])`应返回`true`。
|
||||
|
||||
```js
|
||||
function checkPositive(arr) {
|
||||
// Add your code below this line
|
||||
return arr.some(elem => elem > 0);
|
||||
// Add your code above this line
|
||||
}
|
||||
checkPositive([1, 2, 3, -4, 5]);
|
||||
assert(checkPositive([1, 2, 3, -4, 5]));
|
||||
```
|
||||
|
||||
</section>
|
||||
`checkPositive([1, 2, 3, 4, 5])`应返回`true`。
|
||||
|
||||
```js
|
||||
assert(checkPositive([1, 2, 3, 4, 5]));
|
||||
```
|
||||
|
||||
`checkPositive([-1, -2, -3, -4, -5])`应返回`false`。
|
||||
|
||||
```js
|
||||
assert(!checkPositive([-1, -2, -3, -4, -5]));
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
|
Reference in New Issue
Block a user