如何解决这段来自 Eloquent JS 的代码如何确定主要的写作方向?
我正在学习 Eloquent JavaScript,而 this higher-order function exercise 的答案让我难住了:
function characterScript(code) {
for (let script of SCRIPTS) {
if (script.ranges.some(([from,to]) => {
return code >= from && code < to;
})) {
return script;
}
}
return null;
}
// takes a test function and tells you whether that function
// returns true for any of the elements in the array
function countBy(items,groupName) {
let counts = [];
for (let item of items) {
let name = groupName(item);
let kNown = counts.findindex(c => c.name == name);
if (kNown == -1) {
counts.push({name,count: 1});
} else {
counts[kNown].count++;
}
}
return counts;
}
// returns an array of objects,each of which names a group
// and tells you the number of elements that were found in that group
function dominantDirection(text) {
let scripts = countBy(text,char => {
let script = characterScript(char.codePointAt(0));
return script ? script.direction : "none";
}).filter(({name}) => name != "none");
if (scripts.length == 0) return "ltr";
return scripts.reduce((a,b) => a.count > b.count ? a : b).name;
}
console.log(dominantDirection("Hello!"));
// → ltr
console.log(dominantDirection("hey,مساء الخير"));
// → rtl
此代码返回大型数据集中的主要写入方向,如下所示:
[
{
name: "coptic",ranges: [[994,1008],[11392,11508],[11513,11520]],direction: "ltr",year: -200,living: false,link: "https://en.wikipedia.org/wiki/coptic_alphabet"
},// …
]
我了解如何使用带有 some
方法的循环来查找字符代码返回 true
的任何数组。
我无法理解 countBy
函数或 dominantDirection
函数如何导致底部显示的结果。
这两个函数的细分以及它们如何导致正确的结果将不胜感激!
解决方法
如果你检查一些中间结果会更容易理解。
添加 console.log
以查看 scripts
返回的内容,删除 .name
以查看 reduce
调用的结果:
function dominantDirection(text) {
const scripts = countBy(text,(char) => {
const script = characterScript(char.codePointAt(0));
return (script
? script.direction
: "none"
);
})
.filter(({name}) => name !== "none");
if(scripts.length === 0){
return "ltr";
}
console.log(scripts); // What is the result of the `countBy` function?
return scripts.reduce((a,b) => (a.count > b.count
? a
: b)); // What is the object that the `name` property comes from?
}
现在 dominantDirection("Hello!")
会将 scripts
记录为
[
{ name: "ltr",count: 5 }
]
结果也将是
{ name: "ltr",count: 5 }
dominantDirection("Hey,مساء الخير")
会将 scripts
记录为
[
{ name: "ltr",count: 3 },{ name: "rtl",count: 9 }
]
结果
{ name: "rtl",count: 9 }
scripts
数组来自 countBy
调用,该调用返回每个脚本方向的字符串中有多少代码点的计数。
它尝试通过比较 SCRIPTS
属于哪个 ranges
并获取相应的 codePoint
属性,从每个 direction
中找到相应的脚本。
这个高阶函数 countBy
接受参数 items
和 groupName
。
dominantDirection
使用两个参数调用 countBy
并将其结果存储在 scripts
中。
-
items
是一个可迭代值,在这种情况下是一个字符串(代码点):这只是输入字符串,例如"Hey,مساء الخير"
。根据该值,单个项目(代码点)将被分组到“桶”中并单独计算。 -
groupName
是一个函数,它返回单个代码点(例如一个字符)所属的“桶”的名称(基于代码点本身):在这种情况下,它是箭头函数 { {1}}…char => {
使用单个}
的代码点调用characterScript
并返回相应的脚本对象(您说您理解)。然后它从您的示例中获取脚本的char
,例如direction
用于"ltr"
...{ name: "Coptic",
对象(如果找不到脚本对象,则为}
) .
顺便说一句,"none"
不是一个好名字,因为它需要一个函数,但这个名字暗示了一个字符串。
也许 groupName
更好。
当 groupNameFromItem
遍历字符串 (countBy
) 时,此函数(最初为 for (let item of items)
…char => {
)被调用并分配给 }
({{ 1}})。
由于 name
…let name = groupName(item);
返回脚本的 char => {
,因此 }
变为 direction
、name
或 "ltr"
— 即名称的“桶”。
数组 "rtl"
由 "none"
之类的对象填充。
如果下一个代码点也来自 counts
脚本,则使用 { name: "ltr",count: 1 }
找到该对象,并使用 ltr
增加其 findIndex
。
然后返回这个填充的数组(这是 count
在 ++
中所指的)。
scripts
很容易解释:dominantDirection
和 reduce
是来自 a
数组之一的对象。
如果b
高于scripts
,则返回a.count
,否则返回b.count
;然后将返回的对象用于下一次比较,或者,如果没有其他需要比较的内容,则作为结果返回。
因此,a
调用查找具有最大 b
的对象。
原代码中,最后只返回reduce
,而不是整个对象。
总结:
count
是一个字符串,由来自不同脚本的代码点组成。
name
接受 text
,遍历代码点,调用 countBy
以获取当前代码点的“bucket name”,填充 text
数组(名为 {{1 }},在函数之外)带有 groupName
条目,这些条目告诉您 counts
许多代码点来自 scripts
方向上的脚本。
然后 { name,count }
在这些条目中查找最大的 count
,并返回其 name
。
另外两件事:
-
我了解如何使用带有
reduce
方法的循环来查找字符代码返回count
的任何数组。字符代码本身不返回
name
。 如果代码点some
落入true
(包含)和true
(不包含)之间的任何范围,或者 {{ 1}},否则。 -
本章介绍的是高阶函数,因此了解
some
...true
中的code
参数的工作原理很重要。 我不太确定您对这个概念有多熟悉,但这里有一个更简单的示例,其中计算奇数和偶数并附有一些解释性注释:from
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。