【问题标题】:finding the lowest numeric value in a multidimensional object by property按属性查找多维对象中的最低数值
【发布时间】:2016-04-11 04:30:07
【问题描述】:

我有一个 JSON 对象,它是一个对象数组,我想在其中找到给定属性名称不为空的最低值的对象。

_.min(arr, function(o){
    return o[prop];
});

是我最后一次尝试的,但似乎没有任何选择可以工作或为我提供我想要的。有没有一种干净的方法可以做到这一点?

【问题讨论】:

  • Math.min.apply(0, _.map(arr, function(o){ return o[prop];}));
  • Math.min.apply(0, _.pluck(arr, prop))
  • Math.min.apply 将返回 NaN 如果所有值都不是数字 var arr = [{lol:0},{lol:'lol'}]; Math.min.apply(数学,arr); // NaN
  • @KamijouTouma:这就是为什么你需要先提取数字......你也可以.filter(Number.isFinite) 来防止意外的NaN:[1/0,1,0,-0,Infinity].filter(Number.isFinite) 所以......Math.min.apply(0, _.pluck(arr, prop).filter(Number.isFinite)) 是您正在寻找的机器人:安全快速。

标签: javascript arrays object underscore.js


【解决方案1】:

https://lodash.com/docs#sortByOrder

https://lodash.com/docs#isFinite

https://lodash.com/docs#first

_.first(_.sortByOrder(arr, prop, 'asc', _.isFinite))

最干净最短的方法。

或者如果你不关心 Infinity

https://lodash.com/docs#isNaN

_.first(_.sortByOrder(arr, prop, 'asc', !_.isNaN))

【讨论】:

  • 排序工作量很大,Math.min.apply 不是更快吗?
  • @dandavis 相当肯定 _.sortByOrder 比 _.map 更快,如果所有值都不是数字,则 Math.min.apply 将返回 NaN var arr = [{lol:0},{lol:'lol'}]; Math.min.apply(0, _.map(arr, function(o){ return o['lol'];})); // NaN
  • 我看不出排序如何比转换快,尤其是通过用户空间函数工作的排序,每个元素>n 可以触发多次,并且需要比较逻辑硬编码,而 pluck/map 总是运行 n 次并且不进行比较。
  • @dandavis 经过测试,无法获得性能差异,因为当我尝试获取执行函数所需的时间时,它们都返回 0。
  • 您可以使用performance.now() 来计算单个空循环迭代的时间差;)
【解决方案2】:

这是一个纯 JavaScript 解决方案。不需要额外的库。

var a = [
  {value: null},
  {value: "foo"},
  {value: Infinity},
  {value: 1},
  {value: -2},
  {value: 5},
  {value: 10},
  {value: 5}
]

// Filter away the invalid values
a = a.filter(function(o) {
  return typeof o.value === "number" && Number.isFinite(o.value);
})
// Sort them the way you want
.sort(function(o1, o2) {
  return o1.value > o2.value;
});

// The first object now contains the lowest value
console.log(a);

【讨论】:

  • NaN 也有 Typeof 数 ... Infinity 也是如此
  • [1/0,1,0,-0,Infinity].filter(Number.isFinite)
【解决方案3】:
Array.prototype.min = function() {
    var selector = function(a) {
        return a;
    };
    if(arguments.length>0) {
        selector = arguments[0]; //can also check if it's a function if you don't trust yourself or other developers using this extension
    }
    if(this.length==0) return null;
    var min = this[0];
    for(var i=0;i<this.length;i++) {
        if(selector(min)>selector(this[i])) min=this[i];
    }
    return min;
}

//usage
myArr.min(function(obj) {return obj.intProperty;});

【讨论】:

  • 你试过了吗?因为它不返回 NaN,因为它无法返回 NaN。此代码绝不会尝试调用对数字的隐式强制转换,并将该值用作返回值。事实上,我只是用这行代码测试了这段代码:[{prop:'1'},{prop:'2'}].min(function(o) {return o.prop});,你知道吗?有用。除非是倒退。我搞砸了比较运算符 &lt; 而不是 &gt;。但如果您担心,没有什么能阻止您添加自定义比较回调,或根据您认为适合您的实现修改此代码。
  • 是的,我试过了,现在。它返回正确的结果。 {prop: "1"},即使用户(使用扩展的用户)有责任提供正确、一致的输入。该扩展程序完全按照它应该做的事情。如果您希望将它与更灵活的规则一起使用,请继续添加另一个参数,即比较器回调,以便它可以处理不区分大小写的字符串字母顺序或其他任何内容。 这超出了这个问题的范围
  • 好吧,我刚刚注意到的另一件事是无论如何你都在比较字符串,我应该说[{prop:'prop'},{prop:NaN},{prop:1},{prop:2}].min(function(o) {return o.prop});,因为你会假设它们的最低值是数字而不是字符串文字。您甚至根本不检查该值是否实际上是一个数字,这就是您没有得到 NaN 或错误的原因。标题还说“通过属性在多维对象中找到最低数值”显然他们想要数字而不是像“2”这样的数字的字符串文字版本;)
  • 使用 JS 以外的任何语言都不允许您在数据中出现这种混乱。用户(使用此扩展程序)有责任提供有效数据。无效数据 = 可能的意外结果。我不是来为所有男性问题提供终极解决方案的。如果我开始检查每一个可用的场景,这个扩展将会非常大,以至于没有人会真正使用它。这超出了问题的范围,因为任何非整数值都必须被评估为某些东西,或者只是抛出一个错误。而且他没有要求整数验证器。
  • 看,有很多问题确实不完整。 PHP 回答 SQL 注入,正则表达式解析 HTML,查询 not in 结构,jQuery 用于添加 2 个数字等。然而,你在这里,要求我在一个与验证完全无关的地方验证数据,在一个不要求数据验证的问题。为什么?
猜你喜欢
  • 2018-07-09
  • 1970-01-01
  • 2022-07-08
  • 1970-01-01
  • 1970-01-01
  • 2021-03-05
  • 2014-05-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多