【问题标题】:Get minimum and maximum of object property names that are integers获取整数的对象属性名称的最小值和最大值
【发布时间】:2012-12-21 04:16:29
【问题描述】:

已更新(问题表述有误,见下方注释)

我有一个对象,该对象具有一组以数字命名的属性,如示例所示。 “编号名称”不一定是连续的,我也不知道它们从哪里开始或结束。我知道其他属性不会用数字命名。
我知道 myObject["propName"] 和 myObject.propName 是一样的,但是我特意用第一种方式写,因为 myObject.0 看起来怪怪的,并没有得到所有编辑器的认可。

如何获得最小和最大数组索引?

所以在这种情况下

myObject["0"] = undefined
myObject["1"] = {}
myObject["2"] = undefined
myObject["3"] = {}
myObject["4"] = {}
myObject["5"] = undefined
myObject["someOtherProperty"] = {}

会给我这个

minIndex(myObject) == 1
maxIndex(myObject) == 4

在此编辑之前的所有答案
感谢您的回复。我不应该匆忙发布这个问题,应该在提交之前重新阅读它。已经很晚了,我很着急。我很抱歉。
通过实际看到我的错误陈述(使用数组而不是对象),我认为,根据我重新制定的问题的答案,我可能需要重写我的代码以使用数组而不是对象。我使用对象而不是数组的原因是另一个问题的材料。

目前的努力
我已经尝试找到一种将属性名称转换为数组然后循环遍历它们的方法,但事实证明这很笨拙。我正在寻找一种不易出错且优雅的方式。

【问题讨论】:

  • 顺便说一句...您可以使用 array.splice() 从数组中删除没有丑陋洞的项目。也许这首先消除了这个问题。
  • 我会结束这个问题。这些类型的问题,除了没有表现出任何研究成果外,总是以疯狂的编码竞赛(C3)告终。地球上没有足够的时间来纠正所有答案中的所有问题,如果我出于各种原因对大多数答案投了反对票,愤怒的市民可能会攻击我的家。
  • 哇,一个工作日都没看这个,然后这个。相当震惊。是的,我对真正的 JavaScript 还是很陌生。此外,我认为,在我努力只给出核心问题的过程中,我可能将问题归结为不正确的问题并提出错误的问题。我将尝试审查整个事情。但真的:哎哟
  • @Esailija,您对此提出质疑是对的。重新表述的问题,在 OP 中添加了对您请求的响应
  • @Boris Callens 我更新了我的答案。让我知道这是否适用于“更新的场景”:)

标签: javascript


【解决方案1】:

编辑:啊哈!现在问题变得更有趣了。

解决方案 1: 让我们一次性解决这个问题,好吗?对于最大值:

function maxIndex(obj){
    var max = -1;
    for(var i in myObject){
        var val = parseInt(i);
        if(isFinite(val)){
            if(typeof obj[val] !== 'undefined' && val > max){
                max = val;
            }
        }
    }
    return max;
}

我认为您可以自行将其转换为 min ;)

解决方案 2:在这里,我会将您的 对象 恢复为我们最初认为的样子,以防您真的喜欢其他解决方案之一。那么剩下的答案都适用。

function convertObject(obj){
    var output = [];
    for(var i in myObject){
        var val = parseInt(i);
        if(isFinite(val)){         
            output[val] = obj[i]; //Gotta love JS
        }
    }
    return output;
}

按计划继续!


要找到最小的,从底部开始,一直向上直到找到。

function minIndex(myArray){
    for(var i = 0; i < myArray.length; i++){
        if(typeof myArray[i] !== 'undefined')
            return i;
    }
}

要做到最大,从顶部开始。

function maxIndex(myArray){
    for(var i = myArray.length - 1; i >= 0; i--){
        if(typeof myArray[i] !== 'undefined')
            return i;
    }
}

两者都是最坏情况 O(n)。你真的不能做得更好,因为整个数组可能是空的,你必须检查每个元素是否为正。

编辑:如前所述,您还可以通过简单地编写if(myArray[i]) 来检查某些内容是否未定义。随心所欲。

【讨论】:

  • null == undefined... 我不明白为什么人们不直接使用typeof x == 'undefined',这是一种经过验证的undefined 测试方法。
  • 如果我们要使用 != 不妨使用 if(myArray[i]) ,其次如果您担心性能,只需使用单个循环并返回 {min:1, max :4}
  • @bažmegakapa 只是匆忙而已。我今天一直在很多语言之间跳跃^.^
  • @ngmiceli 还有一件事:! 的优先级高于 ===。我建议改用!==
  • 关于您的编辑:if (myArray[i]) 是一个非常糟糕的主意。它为 undefined 提供 false - 以及所有虚假值。
【解决方案2】:
var myObject = {};
myObject["0"] = undefined;
myObject["1"] = {};
myObject["2"] = undefined;
myObject["3"] = {};
myObject["4"] = {};
myObject["5"] = undefined;
myObject["someOtherProperty"] = {};

var keys = Object.keys(myObject).map(Number).filter(function(a){
    return isFinite(a) && myObject[a];
});

var min = Math.min.apply(Math, keys);
var max = Math.max.apply(Math, keys);

console.log(min, max); //Logs 1 and 4

所有人的文档和兼容性信息:

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/filter

【讨论】:

  • 这看起来很漂亮和整洁 :) 看过 John Resig 的一篇关于使用 apply for max 的帖子。这很好地融合了它。对兼容性有一些担忧,但链接似乎解决了它。很好,谢谢:)
【解决方案3】:

尝试遍历数组,直到找到第一个非undefined 元素。

function minIndex(arr){
    for(var i = 0, len = arr.length; i < len; i++){
        if(arr[i] !== undefined){
            return i;
        }
    }
}

对于最大索引,做同样的事情,除了相反。

function maxIndex(arr){
    for(var i = arr.length-1, len = 0; i >= len; i--){
        if(arr[i] !== undefined){
            return i;
        }
    }
}

【讨论】:

  • 在尝试访问arr[arr.length] 时,maxIndex 不会抛出索引越界异常,还是 undefined 会捕获它?
  • @PhillipSchmidt:undefined 会抓住它,但你是对的。
【解决方案4】:

分钟:

for(var i = 0; i < myArray.length; i++) {
    if(myArray[i] != undefined) {
        return i;
    }
}

最大:

for(var i = myArray.length-1; i >= 0; i--) {
    if(myArray[i] != undefined) {
        return i;
    }
}

【讨论】:

    【解决方案5】:

    试试这样的:

    function minIndex(var array){
       for(var i = 0; i < array.length; i++)
       {
          if(typeof array[i] != "undefined")
          return i;
       }
       return null;
    }
    
    function maxIndex(var array){
       var returnIndex = -1;
       for(var i = 0; i < array.length; i++)
       {
          if(typeof array[i] != "undefined")
          returnIndex = i;
       }
       if(returnIndex !== -1) return returnIndex;
       else return null;
    }
    

    【讨论】:

      【解决方案6】:

      这利用了 for..in 仅迭代定义的元素并使用索引这一事实:

      function minIndex(arr){ for(el in arr){return el} }
      
      function maxIndex(arr){var v; for(el in arr){v = el}; return v }
      

      注意事项: 第二个函数不是很有效,因为它循环遍历整个数组。 如果您明确设置未定义的索引,这将不起作用。

      【讨论】:

      • 在示例中。这些值的字面意思是undefined,所以这不起作用。另外,您不应该将 for...in 用于数组。
      • 刚刚意识到明确的定义。我只是通过添加定义的值来尝试它。我很懒(这是程序员的基本美德)已编辑。
      【解决方案7】:
      var max=0;
      var min=myArray.length;
      for (var i in myArray)
          if (myArray[i]!==undefined)
          {
              max=Math.max(i, max);
              min=Math.min(i, min);
          }
      

      【讨论】:

      • 不要将for...in 用于数组。另外,由于这些值被明确设置为undefined,所有的键都会出现在这里。
      • 当然,您必须测试这些值,但是 for...in 方法的优点是只检查定义的值,而不是从 0 开始的所有可能值。
      • 问题是,在这个例子中,所有的值都是定义的。另外:stackoverflow.com/questions/500504/…
      • 编辑以说明我的意思。
      • 不理解反对票...如果我们有这样的数组,我试图避免遍历 1000 个元素: var a=[]; a[1000]=5;.
      猜你喜欢
      • 1970-01-01
      • 2012-06-23
      • 1970-01-01
      • 1970-01-01
      • 2019-05-08
      • 1970-01-01
      • 1970-01-01
      • 2015-07-29
      • 1970-01-01
      相关资源
      最近更新 更多