【问题标题】:Foreach key where the object[key] meets a precondition对象[key]满足前提条件的foreach键
【发布时间】:2019-07-27 19:10:03
【问题描述】:

我想在不知道第一级键的情况下访问满足条件的嵌套对象的所有第二级元素。

例如:

myObject = {
   foo: {
      element_one : 1,
      element_two : 1,
      ...
   },
   bar: {
      element_one : 3,
      element_two : 4,
      ...
   },
   buzz: {
      element_one : 99,
      element_two : 100,
      ...
   },
   ...
} 

在上面的示例中,我希望能够有效地抓取myObject.<any_key>.element_one === some_number 所在的所有第一级键。

一个明显的解决方案是遍历列表并检查每个元素,但是多次调用此函数会导致计算成本很高。作为备份,我可以创建一个新对象,其中 keys = element_one 并将其用作参考。

但我很想知道是否有更好的方法来处理这个问题?

编辑: 我没有关于元素最大值的先验知识。

【问题讨论】:

  • 是的,迭代是您选择的数据结构的唯一解决方案。如果您确实需要经常这样做,请维护一个单独的数据结构,该结构具有从数字到键列表(或对象本身)的Map。对于您描述的“多次调用”,这将具有最佳性能。我想不出其他任何东西,因为您没有说明该结构的任何其他属性。
  • 明确地说,您将进行迭代(访问每个键),这个过程不能比 O(n) 更好。 @Bergi 建议缓存该结果,因此您可以避免在 m 调用上重做工作,但请注意 O(m*n) = O(n)。

标签: javascript javascript-objects


【解决方案1】:

类似的东西会起作用:

var obj = <YOUR_OBJ>
var final_keys = [];

for(key in obj)
{
 if(a[key].element_one == 1){
   final_keys.push(key);
 }
}
console.log(final_keys);

【讨论】:

  • OP 已经知道:“一个明显的解决方案是遍历列表并检查每个元素
  • 我认为您可以将条件与 Object.values() 一起使用,并使用数组 indexOf 函数进行检查。如需更多信息,请告诉我您想要什么类型的条件?
【解决方案2】:

您可以使用Object.keys 获取对象的第一级键的数组,并使用Array.prototype.filter 在第一级键中进行过滤,其中第二级键具有指定的编号:

myObject = {
   foo: {
      element_one : 1,
      element_two : 1
      },
   bar: {
      element_one : 3,
      element_two : 4
     },
   buzz: {
      element_one : 99,
      element_two : 100
   }
   
} 
console.log(Object.keys(myObject).filter(key => myObject[key].element_one === 99));

【讨论】:

  • OP 已经知道:“一个明显的解决方案是遍历列表并检查每个元素
  • 有趣的评论。但不幸的是,我不知道 element_one 的数字范围是多少。考虑到这一点,维护第二个数据结构可能是更好的解决方案。
【解决方案3】:

所以我将给出两种不同的解决方案。

1) 你得到匹配键的数组

2) 您将获得一个具有匹配键(及其关联值)的新对象

const myObject = {
   foo: {
      element_one : 1,
      element_two : 1,
   },
   bar: {
      element_one : 3,
      element_two : 4,
   },
   dogs: {
      element_one : 1,
      element_two : 4,
   },
   buzz: {
      element_one : 1,
      element_two : 100,
   },
}

const matchingKeys = Object.keys(myObject).filter(key => {
	return myObject[key].element_one === 1
})

// 1st solution: if you want the matching keys only
console.log(matchingKeys)

const objectWithMatchingKeys = Object.keys(myObject).reduce((acc, val) => {
  if (myObject[val].element_one === 1) acc[val] = myObject[val]
  return acc
}, {})

// 2nd solution: if you want the object WITH matching keys
console.log(objectWithMatchingKeys)

您可以通过将硬编码键(例如 element_one)替换为辅助函数中的函数参数来使上述任何解决方案可扩展/可重用!

【讨论】:

    【解决方案4】:

    感谢大家的回复。 我认为考虑到我对任何元素的最小/最大值没有任何控制或知识,它们不一定是有序的; Bergi 和 RK_oo7 的 cmets 是正确的。最有效的解决方案是遍历列表一次并缓存元素值以备将来使用。

    类似这样的:

    var elementIndex = {};
    Object.entries(myObject).forEach(([key, val]) => {
      if (val.element_one in elementIndex) {
         elementIndex[val.element_one].push(key);
      } else {
         elementIndex[val.element_one] = [key];
      }
    });
    

    【讨论】:

      猜你喜欢
      • 2020-03-31
      • 1970-01-01
      • 1970-01-01
      • 2010-10-02
      • 1970-01-01
      • 2013-08-03
      • 2020-01-11
      • 2020-08-29
      • 2015-12-07
      相关资源
      最近更新 更多