JS 循环计数对象

JS Counting objects in loop

提问人:GBM 提问时间:9/27/2023 最后编辑:0stone0GBM 更新时间:9/28/2023 访问量:56

问:

(新手问题)

我试图弄清楚为什么以下代码有效。

目标是从数组元素和 .count(ID 在范围内出现的次数)创建键。

我是这样接近的。

var darray = [["BM","BM","CC","DD","CC","HH","KK","CC"]];
var obj = {}

for(i=0;i<darray.length;i++){
 
    var codes= darray[i][0]
 
    if(obj[codes]){

       obj[codes].count +=1
    }
    else {
      obj[codes] = {count: 1}

    }
}

console.log(obj)

result example:
{
BM: {count:2},
CC: {count:3}

}

这将返回预期的输出,但我的观点是,如果我错过了 else 语句,那么我会得到一个空对象,我不明白为什么 else 语句中的初始化会解决这个问题。 谢谢

我需要了解对象初始化的底层逻辑

JavaScript 数组循环 对象 google-apps-script

评论

1赞 0stone0 9/27/2023
我已将您的代码更改为可运行的代码片段,因此您可以看到它产生了您所说的其他内容。
2赞 Quentin 9/27/2023
如果你删除唯一一个赋值的代码,怎么可能是真的?if(obj[codes])obj[codes]
0赞 trincot 9/27/2023
“我需要了解对象初始化的底层逻辑”:原理很明确:如果你不初始化,你就不......让它初始化。在您的情况下,这意味着条件永远不会为真,因为这要求测试值为......初始化。对此我们还能说什么呢?if
0赞 David 9/27/2023
这是开始熟悉使用调试器的好机会。在调试器中单步执行代码时,哪个操作首先产生意外结果?该操作中使用的值是什么?结果如何?预期的结果是什么?为什么?

答:

1赞 Eyas Valdez 9/27/2023 #1

您的代码片段将只执行一次 for 循环,因为它是在外部数组长度(即 1)上执行的。所以它只看.darraydarray[0][0]

您需要使用内部数组(即 的第一个元素)来遍历键。darray

代码片段中的第二个错误是,在获取 .codes

如果不交换查询,则会出现索引越界错误,因为它会消失

1. darray[0][0]
1. darray[1][0] // out of bounds

var darray = [["BM","BM","CC","DD","CC","HH","KK","CC"]];
var obj = {}

for(i=0;i<darray[0].length;i++){
 
    var codes= darray[0][i]
 
    if(obj[codes]){

       obj[codes].count +=1
    }
    else {
      obj[codes] = {count: 1}

    }
}

console.log(obj)

或者,我建议使用地图,因为对象是固定形状,而地图可以在您使用时更改形状。

0赞 Wimanicesir 9/27/2023 #2

您在此处发布的代码未按预期工作。我做了一些更改以使其正常工作。

var darray = ["BM", "BM", "CC", "DD", "CC", "HH", "KK", "CC"];
var obj = {}

for (i = 0; i < darray.length; i++) {

    var code = darray[i]

    if (obj[code]) {
        obj[code].count += 1
    } else {
        obj[code] = {
            count: 1
        }
    }
}

console.log(obj)

我认为您的问题如下:

为什么没有其他东西就行不通?

好吧,如果我们遵循逻辑,它会检查 obj[code] 是否存在,如果没有,他会在对象中创建此条目。但是,如果您从不将此条目添加到对象中,则它永远无法计算任何值。

但是它与对象初始化没有太大关系,因为这实际上发生在“var obj = {}”的第二条规则中。

0赞 Mr. Polywhirl 9/27/2023 #3

处理这种情况的最简单方法是创建一个函数,该函数采用数组并将每个项减少一些值。

只需将数组的第一项以及可选的访问器传递给函数即可。如果未提供任何值,则值为项本身。

const computeFrequency = (arr, accessor) =>
  Object.fromEntries([...arr.reduce((map, item) => {
    const value = accessor
      ? typeof accessor === 'function'
        ? accessor(item)
        : accessor[item]
      : item;
    const existing = map.get(value) ?? { count: 0 };
    existing.count++;
    return map.set(value, existing);
  }, new Map).entries()]);

const darray = [["BM", "BM", "CC", "DD", "CC", "HH", "KK", "CC"]];
const frequencies = computeFrequency(darray[0]);

console.log(frequencies)
.as-console-wrapper { top: 0; max-height: 100% !important; }

0赞 syzygy 9/28/2023 #4

您尝试访问: .这不会存在于您刚刚创建的空对象上,它只会在您设置仅在 else 语句中出现的 count 对象时存在:obj[codes].count

obj[codes] = {count: 1} / 你告诉对象有使用数字类型的对象变量 'count'

所以 count 是你在 else 语句中手动设置的对象变量,如果你删除它,那么将始终失败,因为 .count 不存在,直到你说它存在obj[codes].count +=1