从一个世纪中寻找预期寿命(Eloquent Javascript练习5.3)

Finding life expectancy from a century ( Eloquent Javascript exercise 5.3)

本文关键字:Eloquent Javascript 练习 寻找 一个      更新时间:2023-09-26

问题

给定一些JSON数据显示一个世纪的平均预期寿命。以下是一些示例JSON数据,因为有相当多的

 '{"name": "Carolus Haverbeke", "sex": "m", "born": 1832, "died": 1905, "father": "Carel Haverbeke", "mother": "Maria van Brussel"}',
  '{"name": "Emma de Milliano", "sex": "f", "born": 1876, "died": 1956, "father": "Petrus de Milliano", "mother": "Sophia van Damme"}',
  '{"name": "Maria de Rycke", "sex": "f", "born": 1683, "died": 1724, "father": "Frederik de Rycke", "mother": "Laurentia van Vlaenderen"}',
  '{"name": "Jan van Brussel", "sex": "m", "born": 1714, "died": 1748, "father": "Jacobus van Brussel", "mother": "Joanna van Rooten"}',

现在输出看起来像

// → 16: 43.5
//   17: 51.2
//   18: 52.8
//   19: 54.8
//   20: 84.7
//   21: 94

当然,侧面的数字指的是你在上的世纪

答案

function average(array) {
  function plus(a, b) { return a + b; }
  return array.reduce(plus) / array.length;
}
function groupBy(array, groupOf) {
  var groups = {};
  array.forEach(function(element) {
    var groupName = groupOf(element);
    if (groupName in groups)
      groups[groupName].push(element);
    else
      groups[groupName] = [element];
  });
  return groups;
}
var byCentury = groupBy(ancestry, function(person) {
  return Math.ceil(person.died / 100);
});
for (var century in byCentury) {
  var ages = byCentury[century].map(function(person) {
    return person.died - person.born;
  });
  console.log(century + ": " + average(ages));
}
// → 16: 43.5
//   17: 51.2
//   18: 52.8
//   19: 54.8
//   20: 84.7
//   21: 94

我的问题

在看了整整15分钟这个问题之后,我没有什么头绪。这个解决方案也让我有点困惑。特别是

if (groupName in groups)但这种说法怎么可能是真的呢?组设置为空数组?

现在剩下的

 groups[groupName].push(element);
    else
      groups[groupName] = [element];

这里groups是一个空对象,而groupName是一个函数。这有点令人困惑。我认为在[]中,我们总是必须有一个数字,例如在一个数组=[1,2,3,4,5]中,我们说array[0]是1。这三行字在说什么?非常感谢。

您误解了这一点是可以原谅的,javascript的后续版本有更好的方法来做到这一点。你真正做的是制作一桶桶相关的东西:

function groupBy(array, groupOf) {
  var groups = {}; // empty (for now)
  array.forEach(function(element) {
    var groupName = groupOf(element); // uses the function groupOf to get a string
    if (groupName in groups) // if that string is already a key in the hash
      groups[groupName].push(element); // push into the array in the hash
    else
      groups[groupName] = [element]; // create an array in that hash with element at its first index
  });
  return groups;
}

这里的代码是有条件地在由组名称键入的对象中创建一个数组,例如groups['foo'][0]将是foo组中的第一个元素。在遍历元素时,按groupName(属性键(将它们排序到bucket(数组(中最初为空的对象中。

现在通常这样做的方式是使用reduce:

array.reduce(function(groups, element) {
  var groupName = groupOf(element);
  if (groupName in groups)
    groups[groupName].push(element);
  else
    groups[groupName] = [element];
  return groups;
}, {});

更新

方括号[]运算符的多种用途:

[]运算符可用于通过JavaScript对象上的字符串键设置/获取属性、设置/获取整数索引处的数组元素、构造数组文字或析构函数绑定。

var foo = {};            // an object literal
foo['bar'] = 'pizza';    // setting the 'bar' property.
console.log(foo['bar']); // accessing 'bar' property, prints 'pizza' to the console.

虽然上面通常写的是foo.bar而不是foo['bar'],在这种情况下是等效的,但方括号表示法可以做点表示法不能做的事情,比如带空格的键或变量:

foo['the pizza'] = 'pepperoni';
var str = 'whatever';
foo[str] = 'psssh yeah right';
console.log(foo['whatever'] === foo.whatever === foo[str]); // true

或者是以数字开头的键,比如"7z"之类的。您也可以执行foo[17] = 'whatever'foo[{}] = 'other thing',但这是个坏主意。键将被静默地转换为字符串("17"answers"[对象对象]"(,这是常见的错误源。您的对象属性键应该始终是字符串或符号(为了完整起见,我提到了这一点,如果您不知道符号是什么,请不要担心(。第一个增加了使foo看起来像数组的混乱,因为它们使用相同的方括号访问,但使用整数标记:

var arr = [];        // an array literal
arr.push('sausage'); // adds an element
console.log(arr[0]); // accesses the first element, prints 'sausage'
arr[0] = 'veggie';   // changes the element at index 0
console.log(arr[0]); // prints 'veggie'

我们在上面构造了一个空数组,但它们不一定是空的:

var ints = [0, 1, 2, 3]; // a four element array
var single = [element];  // creates a one-element array with the value of the variable element

高级使用

2015年对JavaScript的更新为我们带来了destructuring bind,我提到它是为了完整性,但它是一个相对高级的用例:

let arr = [1, 'qux'];
let [something, otherthing] = arr;
console.log(something);  // 1
console.log(otherthing); // 'qux'

减温器上方的第二条管线连接至以下装置:

let something = arr[0];
let otherthing = arr[1];

它也可以用于函数定义:

let sum = function([a, b]) { return a + b; }; // note the brackets
let arr = [2, 8];
console.log(sum(arr)); // 10

上述减温器至:

let sum = function(array) {
  let a = array[0];
  let b = array[1];
  return a + b;
};