【问题标题】:How to get first n elements of an object using lodash?如何使用lodash获取对象的前n个元素?
【发布时间】:2017-01-21 20:39:21
【问题描述】:

我想使用 lodash 从 object(不是数组)中获取前 n 个键/值对。我找到了this answer for underscore,它说使用 first(在 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?

【问题讨论】:

  • 您的预期输出是什么? [ a, b ] ?
  • 我希望得到 {a: 7, b: 8} - 一个带有原始子集的“哈希”(对象)。我或多或少将其视为(类似 perl 的)哈希。
  • 记住一点——对象中的“第一个”键是完全没有意义的。对象属性不需要一致性,因此“前三个”(理论上)可以是任意三个。浏览器通常按插入顺序返回属性,但不依赖这种行为。
  • @vt5491 更新了我的解决方案以反映新的预期输出

标签: javascript underscore.js lodash


【解决方案1】:

如果不编写自定义代码,您无法获取对象的前 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>

如您所见,它与以前几乎相同。语法和执行此任务的方式和 exact 方法可能会有所不同,但要点应该仍然存在 - 您需要排序以保持一致性,然后 然后可以得到任意数量的物品。

【讨论】:

  • 是的,我喜欢这个,因为它具有实用的风格。
  • 不过,我想我正在学习 lodash 偏向于数组。可以在数组中使用哈希,例如 [{a:1}, {b:2}]。所以也许最终的解决方案是避免使用散列(对象)作为容器。但我也发现了 lodash 的“对象”部分。在找到 toPairs 函数后,我运气不错:`> object = {a: 7, b: 8, c: 9} { a: 7, b: 8, c: 9 } > _.chain(object).toPairs(o).take(2).value() [ [ 'a', 7 ], [ 'b', 8 ] ]
  • 那是object = {a: 7, b: 8, c: 9}; _.chain(object).toPairs().take(2).value() 返回:[ [ 'a', 7 ], [ 'b', 8 ] ]
  • 是的,如果更适合您,您当然可以使用toPairs。我发现很多时候,我真的不需要一个对象,而带有[key, value] 的数组就很好了。如果您确实需要一个对象,您可以从对数组中创建一个对象。我现在不记得函数的名称(因为它不是合乎逻辑的fromPairs...),但有可能。因此,您可以将 lodash 代码设置为 toPairs,然后过滤它们,然后将这些对组合成一个新对象。
【解决方案2】:

如果您查看 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);

【讨论】:

  • 感谢您的回复。所以你基本上说的是 lodash 做不到。我尝试使用 lodash 的全部原因是避免编写样板文件,并开始思考“功能性”。但是我确实很欣赏关于未订购对象等的观点。我没有拒绝您的回复,我对此表示感谢,但我确实认为 lodash 不提供此功能令人失望(并且有点令人惊讶)。就像我说的,这不是针对您,只是对 lodash 的一般观察。 p.s.不过我还是喜欢 lodash。
  • @vt5491 - 我明白了。您仍然可以使用take 做您想做的事情,请参阅我更新的答案。希望这在某种程度上有所帮助。
  • @vt5491 - 为你做了一些研究,发现这个人也有类似的问题:P github.com/lodash/lodash/issues/946
  • @SamuelToh - take 不完全一样。它不适用于对象,所以你能做的就是提取键(或作为数组的键值对)然后take 其中的前 N ​​个,但你不能直接做 @987654331 @ 并获取一个包含两个(无论定义如何)属性的对象。
  • 另外,您链接到的那个问题与 OP 的完全不同 - 它是关于 first 在 lodash 中不存在,而在 Underscore 中存在。它与在对象上使用.take/.first 无关。
【解决方案3】:

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

对键进行排序

这是一种使用排序键的可用单行方法(因此保证顺序)。

链接

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

没有链接

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

排序详情

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


重要提示:如之前的答案和 cmets 中所述,即使在最新的 ES 版本中,也无法保证属性的顺序。见this updated SO answer。因此,我正在对键进行排序。

【讨论】:

    猜你喜欢
    • 2022-07-01
    • 1970-01-01
    • 2017-07-03
    • 1970-01-01
    • 2010-12-21
    • 2014-07-23
    • 1970-01-01
    • 2011-04-12
    • 1970-01-01
    相关资源
    最近更新 更多