【问题标题】:Javascript (lodash) function to get an ordered array of object valuesJavascript(lodash)函数获取对象值的有序数组
【发布时间】:2015-08-07 05:15:18
【问题描述】:

(上面的标题可能具有误导性,我愿意接受有关如何改进它的建议。)

我想要的是一个函数,它接受一个Array 和一个Object 作为参数,并按照数组指定的顺序生成一个包含对象值的数组。 IE。第一个参数(数组)可以被认为是一个模式,它定义了对象的值应该存储在结果数组中的顺序。

即:

var arrPersonSchema = [
  'name',
  'age',
  'height'
];

var objPerson = {
  'name': 'fred',
  'age': 35,
  'height': 60
};

var objPerson2 = {
  'age': 22,
  'name': 'jane'
};

function orderedValues(arrSchema, obj) {
  var arrResult = [];
  for(var i = 0; i < arrSchema.length; i++) 
    arrResult[i] = obj[arrSchema[i]];
  return arrResult;
}

orderedValues(arrPersonSchema, objPerson);
// → [ 'fred', 35, 60]

orderedValues(arrPersonSchema, objPerson2);
// → [ 'jane', 22, undefined]

现在显然上面的代码产生了预期的结果,但我的问题是是否有更有效(更快)的方法来使用 lodash 或类似的性能增强 javascript 库(甚至是快速的本机实现)来实现相同的结果)。

从某个角度来看,我要求的是 lodash 函数_.zipObject 的二数组形式的。该函数有两种形式:

(A) 采用单个二维数组(这是 _.pairs 的倒数)

_.zipObject( [['fred', 30], ['barney', 40]] );
// → { 'fred': 30, 'barney': 40 }

(B) 采用两个一维数组:(这是我想要的逆数组)

_.zipObject( ['fred', 'barney'],  [30, 40] );
// → { 'fred': 30, 'barney': 40 }

我指的是第二种形式。例如,可以使用它来生成给定模式数组和值数组的对象。即:

_.zipObject(arrPersonSchema, ['fred', 35, 60]);
// → { 'name': 'fred',  'age': 35,  'height': 60 }

请注意,lodash 函数 _.values不是可接受的答案。虽然它确实会产生一个值数组,但值的顺序是“不能保证的”。我正在寻找的函数的重要方面是结果数组中值的顺序由模式显式定义,并且不依赖于任何隐式排序对象内的属性(例如,基于对象的构造方式等)或函数的任何非官方实现细节等。

更新

感谢所有回复的人。我对 Bergi 的建议感到惊讶,即我的实现(我认为这是“幼稚的”)可能是最快的选择。但我采纳了 Bergi 的建议,并对收到的 4 条建议进行了基准测试。这些结果绝不是权威的。我只是使用 Chrome DevTools Javascript CPU 分析器并为每个测试运行 100000 次试验(每次试验 3 个不同的对象)。你可以看到我用来设置基准的 Plunker here

结果如下:

simpleLoop:   393 ms
lodashAt:     917 ms
nativeMap:    719 ms
modArgs:    13741 ms
  • simpleLoop 是我写的函数(又名orderedValues
  • lodashAtAdam Boduch 建议的 lodash 函数 _.at()
  • nativeMapKlaster_1推荐的函数的ES5版本
  • modArgs 是列出的函数 Bergi(需要注意的是它可能不会比我的函数快。)

我有点不确定该选择谁的答案,因为我实际上一次提出了几个不同的问题。 Adam Boduch 给出了基于 lodash 的最佳答案,这正是我所寻找的 zipObject 函数的“逆”函数。 Bergi 的 lodash 函数没有那么简洁(结果证明它要慢得多)。然而,Bergi 指出我简单的orderedValues 函数可能是最快的,他是对的。回顾我的问题,尤其是包含“......我的问题是是否有更有效(更快)的方法......”的行,看来 Bergi 实际上回答得最好,指出确实没有不是比我建议的方法更快的方法。因此,尽管 Adam Boduch 的回答很准确,但我还是决定选择 Bergi 的。再次感谢大家!

【问题讨论】:

  • 为什么不直接使用 const f = (order, object) =&gt; order.map(key =&gt; object[key]) 或 ES5 等价物?
  • 嗯,你已经写了那个快速原生实现,并称之为orderedValues?!几乎没有什么可以让这变得更好。 Lodash 也一次只穿一条腿。

标签: javascript arrays performance function lodash


【解决方案1】:

我会为此使用at()

_.at(objPerson, arrPersonSchema);
// → ["fred", 35, 60]

_.at(objPerson2, arrPersonSchema)
// → ["jane", 22, undefined]

【讨论】:

    【解决方案2】:
    function orderedValues(arrSchema, obj) {
      var arrResult = [];
      for(var i = 0; i < arrSchema.length; i++) 
        arrResult[i] = obj[arrSchema[i]];
      return arrResult;
    }
    

    这是最好的。它是原生 JS,速度非常快。

    如果你坚持使用 lodash,就这样吧:

    var orderedValues = _.modArgs(_.map, [_.identity, _.propertyOf])
    

    这可能会使您的代码更短且更具表现力,但速度不会更快。如果需要,您可以自己对它们进行基准测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-05
      • 1970-01-01
      • 1970-01-01
      • 2021-05-16
      • 1970-01-01
      • 1970-01-01
      • 2021-04-27
      相关资源
      最近更新 更多