Javascript (lodash) 函数获取 object 值的有序数组

Javascript (lodash) function to get an ordered array of object values

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

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

即:

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 库来实现相同的结果(甚至是快速的本机实现)。

从某种角度来看,我要求的是 inverse 的 two-array 形式的 lodash 函数 _.zipObject。该函数有两种形式:

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

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

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

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

我指的是第二种形式。例如,可以使用它在给定模式数组和值数组的情况下生成 object。即:

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

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

更新

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

结果如下:

simpleLoop:   393 ms
lodashAt:     917 ms
nativeMap:    719 ms
modArgs:    13741 ms

我有点不确定谁对 select 的回答,因为我实际上同时提出了几个不同的问题。 Adam Boduch 给出了最好的 lodash-based 答案,这正是我一直在寻找的 "inverse" 到 zipObject 函数。 Bergi 的 lodash 函数没有那么简洁(结果证明它慢得多)。但是,Bergi 指出我的简单 orderedValues 函数可能是最快的,他是对的。回顾我的问题,尤其是包含“……我的问题是是否有更有效(更快)的方法……”的那一行,看来 Bergi 实际上回答得最好,他指出确实没有这是一种比我提出的方法更快的方法。因此,虽然 Adam Boduch 的回答是 spot-on,但我还是决定 select Bergi 的回答。再次感谢大家!

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])

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

为此我会使用 at()

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

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