【问题标题】:Loop through an object of objects循环遍历对象的对象
【发布时间】:2018-08-24 12:37:57
【问题描述】:

有一个对象包含具有这种形式的对象:

bigObject: {
    "a - values": { atr: true}
    "a - items": { atr: true}
    "a - others": { atr: false}
    "b - values": { atr: true}
    "b - items": { atr: true}
    "b - others": { atr: false}
    "c - values": { atr: false}
    "c - items": { atr: true}
    "c - others": { atr: false}
}

我在函数中使用这个对象来检查每次属性之一更改其布尔值时:onButtonClicked(item)

它做了类似的事情:

onButtonClicked(item) {
    bigObject[item.id].atr= !bigObject[item.id].atr;
}

在这个函数中,我想拆分它们以便能够分别检查以abc 开头的对象的值。为此我做到了:const toCheck = item.id.split("-")[0];

这很好用,如果单击了以 a 开头的对象,它将只获取该对象。

下一步是检查特定字母是否同时存在truefalse 属性。

为此,我尝试这样做:

let countFalse = 0;
let countTrue = 0;

 bigObject.forEach(x => {
    if ((x.split("-")[0]) === toCheck) {
        if (x.atr) {
            countTrue++;
        } else countFalse++;
    }
    if (countTrue && countFalse) {
        console.log("has both true and false attributes");
    } else console.log("nope");
 });

所以我拆分了原始名称以摆脱(值、项目、其他),然后我尝试计算真假属性。如果两者都有,则显示一条消息,否则,没有。

出了点问题,但我不明白是什么。有什么想法吗?

【问题讨论】:

  • 你从哪里得到forEach
  • @NinaScholz 修改了它
  • 最后的 if 语句不应该在循环之外。你得到什么输出?
  • 我得到的错误是bigObject.forEach is not a function
  • 您会收到该错误,因为 forEach 用于数组而不是对象文字

标签: javascript loops for-loop foreach iterator


【解决方案1】:

您可以通过' - ' 而不是'-' 拆分来迭代条目。

var bigObject = { "a - values": { atr: true }, "a - items": { atr: true }, "a - others": { atr: false }, "b - values": { atr: true }, "b - items": { atr: true }, "b - others": { atr: false }, "c - values": { atr: false }, "c - items": { atr: true }, "c - others": { atr: false } },
    countFalse = 0,
    countTrue = 0,
    toCheck = 'a';

Object.entries(bigObject).forEach(([k, v]) => {
    if (k.split(" - ")[0] !== toCheck) {
        return;
    }
    if (v.atr) {
        countTrue++;
    } else {
        countFalse++;
    }
});
if (countTrue && countFalse) {
    console.log("has both true and false attributes");
} else {
    console.log("nope");
}

一个更紧凑的版本,带有一个用于计数的对象。

var object = { "a - values": { atr: true }, "a - items": { atr: true }, "a - others": { atr: false }, "b - values": { atr: true }, "b - items": { atr: true }, "b - others": { atr: false }, "c - values": { atr: false }, "c - items": { atr: true }, "c - others": { atr: false } },
    count = { false: 0, true: 0 },
    toCheck = 'a';

Object.entries(object).forEach(([k, { atr }]) => count[atr] += k.startsWith(toCheck));

if (count.true && count.false) {
    console.log("has both true and false attributes");
} else {
    console.log("nope");
}

console.log(count);

【讨论】:

  • @VigneshRaja,箭头函数也不受支持,但 op 正在使用它,在 let 旁边。 => ES6
  • 第一个版本不适合我。 countTrue 和 countFalse 始终为 0。但第二个很好。
【解决方案2】:

据我所知,forEach 不会迭代对象。我建议你使用

const bigObjectKeys = Object.keys(bigObject)

比这样迭代:

bigObjectKeys.forEach(元素 => { 大对象[元素] ...})

或者使用lodash forEach,它可以遍历对象。

https://lodash.com/docs/4.17.10#forEach

【讨论】:

    【解决方案3】:

    你做错了需要修复的地方:

    1. 遍历对象的keys/entries
    2. - 分开,而不是与-
    3. 仅在您完成对所有元素的迭代后使用if 进行检查。

    var countFalse = 0;
    var countTrue = 0;
    
    var bigObject= {
        "a - values": { atr: true},
        "a - items": { atr: true},
        "a - others": { atr: false},
        "b - values": { atr: true},
        "b - items": { atr: true},
        "b - others": { atr: false},
        "c - values": { atr: false},
        "c - items": { atr: true},
        "c - others": { atr: false}
    }
    var toCheck = "a";
     Object.keys(bigObject).forEach(x => {
        if ((x.split(" - ")[0]) === toCheck) {
            if (bigObject[x].atr) {
                countTrue++;
            } else countFalse++;
        }
     });
     
     if (countTrue && countFalse) {
            console.log("has both true and false attributes");
        } else console.log("nope");

    为了提高效率,

    var countFalse = 0, countTrue = 0;
    
    var bigObject= {
        "a - values": { atr: true},
        "a - items": { atr: false},
        "a - others": { atr: false},
        "b - values": { atr: true},
        "b - items": { atr: true},
        "b - others": { atr: false},
        "c - values": { atr: false},
        "c - items": { atr: true},
        "c - others": { atr: false}
    }
    
    var toCheck = "a";
    
    Object.keys(bigObject).forEach(x => {
      if ((x.split(" - ")[0] === toCheck) && !(countTrue>0 && countFalse>0))
      {
          bigObject[x].atr ? countTrue++ : countFalse++;
      }
    });
    if (countTrue && countFalse) {
          console.log("has both true and false attributes");
      } else console.log("nope");

    【讨论】:

      【解决方案4】:

      可以在对象条目上使用Array#filterArray#every

      const isMatching = (str) =>{
        const arr = Object.entries(bigObject).filter(e=> e[0].startsWith(str));
        // makes sure every entry has same `atr` as the first entry  
        return arr.every(e => e[1].atr === arr[0][1].atr);
      }
      
      ['a','b','c'].forEach(s => console.log(s, isMatching(s)))
      <script>
      const bigObject= {
          "a - values": { atr: true},
          "a - items": { atr: true},
          "a - others": { atr: false},
          "b - values": { atr: true},
          "b - items": { atr: true},
          "b - others": { atr: false},
          "c - values": { atr: false},
          "c - items": { atr: false},
          "c - others": { atr: false}
      }
      </script>

      【讨论】:

        猜你喜欢
        • 2020-06-09
        • 2014-02-22
        • 2020-12-06
        • 1970-01-01
        • 1970-01-01
        • 2020-04-30
        • 2017-06-12
        • 2015-10-31
        • 2014-11-30
        相关资源
        最近更新 更多