如何使用lodash获取对象的前n个元素?

时间:2016-09-14 06:19:56

标签: javascript underscore.js lodash

我想使用lodash从对象(不是数组)中获取前n个键/值对。我发现this answer for underscore表示首先使用 (在lodash中不存在),或者使用 take (仅适用于数组)。

示例节点会话尝试从对象获取'a:7'和'b:8'对:

> var ld=require("lodash")
undefined
> var o={a:7, b:8, c:9}
undefined
> ld.keys(o)
[ 'a', 'b', 'c' ]
> ld.take(o, 2)
[]
> ld.first(o, 2)
undefined
> 

当然,使用lodash必须有一些简单的方法来做到这一点,但对于我的生活,我找不到任何东西。也许我不得不诉诸本地的js?

3 个答案:

答案 0 :(得分:6)

如果不编写自定义代码,则无法获取对象的前N个元素。这是因为有no ordering of the elements in objects,所以如果有一个库函数,它永远不会保证给你你期望的元素。给出像

这样的对象
var obj = {  b: 3, y: 2, a: 1 };

目前尚不清楚“前2”是指什么 - 您想要ab,因为这是字母顺序吗?如果是这样,他们是否按顺序?如果没有,您想要by,因为它们首先出现吗?也许您想要ay,因为它们的值最低?

除了不重复之外,您无法保证获得的内容,因此所有这些组合都是有效的。此外,您可以按任意顺序获取ya同样有效的输出您可能更喜欢其中一种或另一种但一般情况下它不正确。

有很多方法,但你必须接受你需要处理非订单。

纯JavaScript解决方案。

function firstN(obj, n) {
  return Object.keys(obj) //get the keys out
    .sort() //this will ensure consistent ordering of what you will get back. If you want something in non-aphabetical order, you will need to supply a custom sorting function
    .slice(0, n) //get the first N
    .reduce(function(memo, current) { //generate a new object out of them
      memo[current] = obj[current]
      return memo;
    }, {})
}
var obj = { b: 2, y: 25, a: 1 }

console.log( firstN(obj, 2) );

这是使用Object.keysArray.prototype.sortArray.prototype.reduce

使用lodash可以实现同样的效果,但并不比这更简洁 - 它将涉及调用类似的功能。它可以这样做,例如:

function firstN(obj, n) {
  return _.chain(obj)
    .keys()
    .sort()
    .take(n)
    .reduce(function(memo, current) {
      memo[current] = obj[current];
      return memo;
    }, {})
    .value();
}

var obj = { b: 2, y: 25, a: 1 }
      
console.log( firstN(obj, 2) );
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

正如您所看到的,它与以前几乎一样。语法和完全方法可能会有不同的方法,但主要观点应该仍然存在 - 您需要排序一致性,然后你可以获得任意数量的物品。

答案 1 :(得分:4)

如果查看first的loadash文档。它只接受一个数组作为参数,这可能不是要使用的API。

请参阅:https://lodash.com/docs/3.10.1#first


以下是使用标准Javascript API解决问题的方法。

这里的问题是您可以使用Object.keys(...)[index] API根据位置检索元素的键。

然后您需要做的只是循环n次,并使用派生键将其推送到另一个对象。

var firstN = 2;
var o={a:7, b:8, c:9};
var result = {};

for (var index=0; index < firstN; index++) {
  var key = Object.keys(o)[index];
  result[key] = o[key];
}

console.log(result);

答案 2 :(得分:0)

没有直接解决方案。受先前答案和评论的启发,并阅读了几篇有关非保证属性顺序的文章,我创建了一个解决方案,首先对键进行排序。

对键进行排序

这是一种具有排序键的可用单线方法(因此保证了顺序)。

连锁

_.chain(object).toPairs().sortBy(0).take(2).fromPairs().value()

不链接

_.fromPairs(_.take(_.sortBy(_.toPairs(object), 0), 2)),

排序细节

sortBy(0)通过(索引0)对我们的集合进行排序。首先,由toPairs()原始对象转换为成对数组(每个 pair 是一个数组[key, value] ),然后按这些的前值排序(key pair 中具有索引0)。


重要:如先前的答案和评论所述,即使在最新的ES版本中,也不能保证属性的顺序。参见this updated SO answer。因此,我正在对键进行排序。