代码之家  ›  专栏  ›  技术社区  ›  totalnoob

数组减少,对象作为累加器

  •  -2
  • totalnoob  · 技术社区  · 6 年前

    具有

    let str = "baaabbabbsbsssssabbaaaa";
    

    用这个

    [...str].reduce((characterMap, char) => {
        if (!characterMap[char]) characterMap[char] = 1;
        else characterMap[char]++;
        return characterMap;
    }, {})
    

    我得到B:8,A:9,S:6

    但当我把它缩短到这个长度时,

    [...str].reduce((characterMap, char) => !characterMap[char] ? characterMap[char] = 1 : characterMap[char]++, {});
    

    它打印出1而不是b:8、a:9、s:6

    为什么?

    我使用reduce是不是一开始就错了?

    3 回复  |  直到 6 年前
        1
  •  4
  •   T.J. Crowder    6 年前

    我怎么缩短这个?

    通过:

    1. 不想把它塞进 reduce . -) 减少 当累加器值 变化 . 在你的情况下,没有。

    2. 不使用数组包装。字符串是不可重复的,所以直接使用这个事实。

    3. 使用 curiously-powerful || operator _如果不存在,则默认字符计数。

    只需使用一个循环:

    const characterMap = {};
    for (const char of str) {
        characterMap[char] = (characterMap[char] || 0) + 1;
    }
    

    活生生的例子:

    let str = "baaabbabbsbsssssabbaaaa";
    const characterMap = {};
    for (const char of str) {
        characterMap[char] = (characterMap[char] || 0) + 1;
    }
    console.log(characterMap);

    但是如果你 真正地 想用 减少 ,您可以应用 γ 技巧和使用一个较短的名字:

    const characterMap = [...str].reduce((acc, ch) => {
        acc[ch] = (acc[ch] || 0) + 1;
        return acc;
    }, {});
    

    活生生的例子:

    let str = "baaabbabbsbsssssabbaaaa";
    const characterMap = [...str].reduce((acc, ch) => {
        acc[ch] = (acc[ch] || 0) + 1;
        return acc;
    }, {});
    console.log(characterMap);

    您可以(ab)使用逗号运算符将其强制转换为简洁的箭头函数,但代价是可读性和可维护性(imho)。

    但当我把它缩短到这个长度时,

    [...str].reduce((characterMap, char) => !characterMap[char] ? characterMap[char] = 1 : characterMap[char]++, {});
    

    它打印出1而不是b:8、a:9、s:6

    为什么?

    因为回调函数返回 !characterMap[char] ? characterMap[char] = 1 : characterMap[char]++ ,而不是对象。所以对它的后续调用会得到这个数字,而不是对象,以及 characterMap[char] 总是错误的(因为 1["a"] undefined 等)。


    γ (在我贫血的博客上)

        2
  •  1
  •   Nina Scholz    6 年前

    因此,您需要使用重新燃烧的蓄能器。

    var str = "baaabbabbsbsssssabbaaaa",
        result = [...str].reduce((characterMap, char) => {
            characterMap[char] = (characterMap[char] || 0) + 1; // take default value of zero
            return characterMap;
        }, {});
    
    console.log(result)

    但当我把它缩短到这个长度时,

    [...str].reduce((characterMap, char) => !characterMap[char] ? characterMap[char] = 1 : characterMap[char]++, {});
    

    它打印出1而不是 { b: 8, a: 9, s: 6 }

    为什么?

    因为在第一个循环中

    !characterMap[char] ? characterMap[char] = 1 : characterMap[char]++
    

    走这条路

    !characterMap[char] ? characterMap[char] = 1 : characterMap[char]++
    ^^^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^^^^^^
    true                  characterMap['b'] = 1
    

    收益率 1

    在接下来的所有迭代中,你都取这个数字 并试图得到一个财产 a (或字符串的所有后续字母),即 undefined

    !characterMap[char] ? characterMap[char] = 1 : characterMap[char]++
    ^^^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^^^^^^
    !1['a']
    true                  1['b'] = 1
    

    结果是

        3
  •  0
  •   trincot Jakube    6 年前

    如果要坚持使用箭头表达式语法,可以使用 comma operator :

    [...str].reduce((characterMap, chr) => 
        (characterMap[chr] = (characterMap[chr] || 0) + 1, characterMap), {});
    

    或者你可以使用 Object.assign :

    [...str].reduce((characterMap, chr) => 
        Object.assign(characterMap, {[chr]: (characterMap[chr] || 0) + 1}), {});