为什么 reduce 以这种方式工作?

Why is reduce working this way?

我写了一个函数来满足以下条件:

"编写一个函数,给定一个字符串,生成所有字符索引的映射。例如, indexes("Mississippi") 应该 return 一个映射,将 'M' 与集合 {0} 关联,'i' 与集合 {1, 4, 7, 10} 关联,并且 等等。"

但为什么在我的实现中 i 的第一个值是 1,从而切断了 M

var s = 'Mississippi';

function indexes(s) {
  var acc = {};

  return s.split('').reduce(function(p, c, i) {
    if (!acc[c]) {
      acc[c] = [i];
    } else {
      acc[c].push(i);
    }

    return acc
  });
}
console.log(indexes(s)); // Object {i: Array[4], s: Array[4], p: Array[2]}

因为您没有为累加器指定初始值,所以对回调的第一次调用在您的数组中有前 两个 个条目(例如,p 将是 "M"c 将是 "i"),但你没有使用 p,所以你最终会错过 "M".

不提供初始值在进行直接求和时很有用(例如),但对于 这种 之类的事情,我发现最简单的方法是使用 reduce 来提供初始值,像这样:

var s = 'Mississippi';

function indexes(s) {
  // Note: No `acc` here
  return s.split('').reduce(function(p, c, i) {
    // Note: Using `p` here
    if (!p[c]) {
      p[c] = [i];
    } else {
      p[c].push(i);
    }

    return p;
  }, {});
  // ^^-- Initializing the accumulator here
}
snippet.log(JSON.stringify(indexes(s))); // {"M":[0],"i":[1,4,7,10],"s":[2,3,5,6],"p":[8,9]}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

如果您更愿意继续使用外部 acc,我可能会使用 forEach 而不是 reduce