【问题标题】:Efficient way to filter an object by key value按键值过滤对象的有效方法
【发布时间】:2018-09-10 22:34:11
【问题描述】:

我需要用 sorted keys:

创建一个对象的蜡烛值
 var obj = [{1: 'a'}, {2:'b'}, {3:'c'}, {4:'d'}, {5:'e'},{6: 'a'}, {7:'b'},{8:'c'}, {9:'d'}, {10:'e'}]

根据键过滤此对象的最有效方法是什么?

例如,我想要:用2 < keys <56 < keys < 9 过滤的obj

(实际上,键是时间戳,值是价格数据)

编辑: 这是对象。这就是我所说的排序

 var obj = [{1: 'a'}, {2:'b'}, {3:'c'}, {4:'d'}, {5:'e'},{6: 'a'}, {7:'b'},{8:'c'}, {9:'d'}, {10:'e'}]

【问题讨论】:

  • 考虑改用时间戳价格元组数组,您将获得正确的顺序并且可以使用filter
  • 遍历键并创建一个新对象。不觉得太难。
  • 现在你有了一个对象数组,每个对象都有唯一的键。这是一个可怕的结构。你控制源头吗?
  • @charlietfl 我可以控制结构
  • 您刚刚编辑了问题以将格式从对象更改为对象数组。只要您可以更改数据格式,您就应该一直按照@Bergi 的建议制作一个元组数组,例如[(1, 'a'), (2, 'b')] 或真实对象:[{time: 1, value: 'a'}]。像这样的键中有数据很奇怪。

标签: javascript arrays object


【解决方案1】:

您可以使用 Object.keys 获取密钥并通过 reduce 来创建一个符合条件的 kv 对的新对象

var obj = {1: 'a', 2:'b', 3:'c', 4:'d', 5:'e',6: 'a', 7:'b',8:'c', 9:'d', 10:'e'}
var res = Object.keys(obj).reduce((acc, elem) => {
	if (elem > 2 && elem < 5) acc[elem] = obj[elem]
	return acc
}, {})
console.log(res)

看起来 obj 已更改
你可以过滤新的 obj 一个简单的 .filter()

var res = obj.filter(elem => Object.keys(elem)[0] > 2 && Object.keys(elem)[0] < 5)

如果您决定在评论中使用该结构

var obj = [{time: 1, value: 'a'},{time: 2, value: 'b'},{time: 3, value: 'c'},{time: 4, value: 'd'}]
var res = obj.filter(elem => elem.time > 2 && elem.time < 5)

【讨论】:

  • 哪个更有效率,第一个答案还是最后一个?我将相应地编辑我的 obj
  • @TSR 就像 Mark Meyer 评论的那样,最明智的方法是拥有一个可以过滤的对象数组,例如 [{time: 1, value: 'a'}],从而消除对 Object.keys 的需求 - 很难判断哪个是性能最高(以及在哪个浏览器中),所以我建议你自己测试一下
  • 我同意,这样的结构要好得多,对于上述两种方法,我在运行时没有显着差异
  • 是像 [{time: 1, value: 'a'}] 这样更好,因为它是排序的,还是仅仅因为它是这样构造的,不管顺序如何?
  • 我会说它只是更好地工作,你不需要一遍又一遍地调用 Object.keys,而且不太可能出现问题
【解决方案2】:

简单的Objet.keysreduce 使用有限的键集创建新对象。

var obj = {1: 'a', 2:'b', 3:'c', 4:'d', 5:'e',6: 'a', 7:'b',8:'c', 9:'d', 10:'e'}

var filtered = Object.keys(obj).reduce((o, k) => {
  const num = Number(k)
  if (num > 4 && num < 9) {
   o[k] = obj[k]
  }
  return o
}, {})

console.log(filtered)

只是一个警告,对象键可能不是按数字顺序排列的。因此,当您输出它们时,not guaranteed 5 将在 6 之前。

【讨论】:

    【解决方案3】:

    如果你使用的是lodash,那么简单如下:

    const _ = require('lodash');
    var obj = {1: 'a', 2:'b', 3:'c', 4:'d', 5:'e',6: 'a', 7:'b',8:'c', 9:'d', 10:'e'};
    filtered = _.pickBy(obj,(val,key) =>{return ((key > 2) && (key < 5))})
    

    【讨论】:

      【解决方案4】:

      您需要先对键进行排序,然后使用过滤器和排序值创建新对象

      我将其更改为 Map,因为不保证对对象键进行排序

      const obj =  {1: 'a', 2:'b', 4:'c', 3:'d', 5:'e',6: 'a', 7:'b',8:'c', 9:'d', 10:'e'};
      
      const newObj = new Map();
      Object.keys(obj).filter(key =>{
      
          return (key > 2 && key < 5)
          }).sort().forEach(key=>{
            newObj.set(key,obj[key])
      
      
          })

      【讨论】:

      • 无法保证对象上键的顺序(即使您在创建新对象之前对其进行排序)
      【解决方案5】:

      正如我所见,你有一个数组而不是一个对象。使用filterObject.keys 以及类似((2&lt;key &amp;&amp; key&lt;5) || (6&lt;key &amp;&amp; key&lt; 9)) 的条件

      var arr = [{1: 'a'}, {2:'b'}, {3:'c'}, {4:'d'}, {5:'e'},{6: 'a'}, {7:'b'},{8:'c'}, {9:'d'}, {10:'e'}]
      
      var newArr = arr.filter((o=>{
          let k = Object.keys(o);
          if((2<k[0] && k[0]<5) || (6<k[0] && k[0]< 9)){
              return true;
          }
      }))
      
      console.log(newArr)

      【讨论】:

        【解决方案6】:

        喜欢这样吗?

        keys() 会给你一个对象键数组,你可以过滤

        var obj = {1: 'a', 2:'b', 3:'c', 4:'d', 5:'e',6: 'a', 7:'b',8:'c', 9:'d', 10:'e'};
        keys(obj).filter((a)=> parseInt(a) > 2 && parseInt(a) <5 );
        

        【讨论】:

        • 你的意思是Object.keys()。没有全局keys()方法
        • 然而,一个键是一个字符串,所以你不能(不应该)直接将它与一个整数进行比较
        • 这只会返回数组中的键,而不是“过滤对象”
        • @charlietfl - 我也不认为有 keys 方法,但在 Chrome 中确实存在。猜猜它是新的。
        • @tymeJV 嗯...在 Firefox 中没有类似的东西。说它是一个“命令行 API”。想知道这是否与开发工具有关?
        猜你喜欢
        • 2019-02-22
        • 1970-01-01
        • 1970-01-01
        • 2021-05-04
        • 2018-04-03
        • 1970-01-01
        • 2021-04-03
        • 1970-01-01
        相关资源
        最近更新 更多