【问题标题】:Checking if element exists in array without iterating through it检查数组中是否存在元素而不遍历它
【发布时间】:2014-10-16 21:50:57
【问题描述】:

我的数组:

tempListArray = "[{"id":"12","value":false},{"id":"10","value":false},{"id":"9","value":false},{"id":"8","value":false}]";

要检查一个元素是否存在,我会这样做:

for (var i in tempListArray) {
    //check flag
    if (tempListArray[i].id == Id) {
        flagExistsLoop = 1;
        break;
    }
} 

无论如何,我可以在不循环整个数组的情况下检查 Id 是否存在。如果说我有 100 个元素,基本上我会担心性能。

谢谢

【问题讨论】:

  • 100 个元素?那真的没什么。别担心。
  • for...in 循环是迭代数组的不好方法。
  • 看看这个post我认为这是你需要的。

标签: javascript arrays performance


【解决方案1】:

不,如果不使用自定义字典对象(您真的不想这样做),没有比对所有包含的对象进行“全面扫描”更快的方法了。

作为一般经验法则,在迭代总数达到 5 位(通常为 6 或 7 位)之前,不要担心任何语言或任何情况下的性能。扫描包含 100 个元素的表应该只需几毫秒最坏的。在注意到性能影响之前担心性能影响是worst kinds of premature optimization 之一。

【讨论】:

  • 它是否取决于您运行它的设备?我正在移动设备上测试 for 循环
  • 当然设备很重要,但可以肯定地说,任何现代移动设备都应该在一秒钟内以及迭代 100 个数组项。
  • 任何现代移动设备都应该在 十分之一秒 秒内迭代 百万 个数组项。
【解决方案2】:

不,如果不迭代数组,您无法知道这一点。

但是,请注意for...in 循环是迭代数组的不好方法:

  • 不保证它会按顺序迭代数组
  • 它还将迭代(可枚举的)非数字自身属性
  • 它还将迭代来自原型的(可枚举的)属性,即在Array.prototypeObject.protoype 中定义的属性。

我会使用其中之一:

  • for 带有数字索引的循环:

    for (var i=0; i<tempListArray.length; ++i) {
        if (tempListArray[i].id == Id) {
            flagExistsLoop = 1;
            break;
        }
    } 
    
  • Array.prototype.some(EcmaScript 5):

    var flagExistsLoop = tempListArray.some(function(item) {
        return item.id == Id;
    });
    

    注意它可能比其他的慢,因为它在每一步都调用一个函数。

  • for...of 循环(EcmaScript 6):

    for (var item of tempListArray) {
        if (item.id == Id) {
            flagExistsLoop = 1;
            break;
        }
    } 
    

【讨论】:

    【解决方案3】:

    根据您的情况,您可以使用Array.indexOf(),如果该项目不存在,它将返回 -1。

    虽然它可能在幕后进行迭代,但代码更简洁。还要注意如何在 javascript 中进行对象比较,其中两个对象不相等,即使它们的值可能相等。见下文:

    var tempListArray = [{"id":"12","value":false},{"id":"10","value":false},{"id":"9","value":false},{"id":"8","value":false}];
    
    var check1 = tempListArray[2];
    var check2 = {"id":"9","value":false};
    
    doCheck(tempListArray, check1);
    doCheck(tempListArray, check2);
    
    function doCheck(array, item) {
      var index = array.indexOf(item);
      
      if (index === -1)
        document.write("not in array<br/>");
      else
        document.write("exists at index " + index + "<br/>");
    }

    【讨论】:

    • array.indexOf 比 for 循环快吗?
    • 不,循环与indexOf() 的性能应该相同。 indexOf() 的好处是代码的简单性和可读性,更不用说它是一行而不是几行。
    【解决方案4】:

    尝试使用php.js 它可能会有所帮助,同时您可以使用相同的 php 函数名称并且它具有一些有用的功能

    【讨论】:

      【解决方案5】:

      如果不遍历元素就没有办法(这很神奇)。

      但是,您可以考虑使用对象而不是数组。该对象将使用(可能是唯一的)id 值作为键,并且该值可以具有您现在拥有的相同结构(或没有多余的id 属性)。这样,您可以有效地确定id 是否已经存在。

      【讨论】:

      • 原来是一个JSON对象,我需要解析成一个数组。我感兴趣的只是ID。是否值得进行搜索以查看 JSON 字符串中的 id 是否与 ID 匹配
      • 如果你无论如何都要解析整个字符串,那么真的没有问题,是吗?无论如何,您将不得不查看所有数据,因此在解析期间进行检查。或者,您是从 JSON 对象开始的吗?在那种的情况下,使用现有的对象来做检查(你仍然没有真正的问题)。
      【解决方案6】:

      在有限的情况下有一个可能的作弊方法:) 这很神奇……咳咳(数学)

      假设你有 3 个元素:

      • 1
      • 2
      • 3

      并且您想知道其中一个是否在数组中而不对其进行迭代...

      我们可以创建一个包含数组的数字风格的数字。我们通过为元素分配素数来做到这一点:

      • 1 - 2
      • 2 - 3
      • 3 - 5

      数组,所以当我们添加第 2 项时,我们通过检查(如果 Flavor!=0 && (Flavor%3)!=0)然后添加素数 Flavor 来检查数组是否已经包含与该项关联的素数*=3;

      现在我们可以通过查看数字来判断第二个元素在数组中。

      如果 Flavor!=0 && (Flavor%3)==0 // 它就在那里!

      当然,这仅限于计算机可以处理的数字表示。对于较小的数组大小(1-3 个元素),扫描速度可能仍然更快。但这只是一个想法。

      但基础非常健全。但是,如果您无法将元素与一组素数一一关联,则此方法将变得不可用。您需要提前计算素数。并验证它们的乘积是更少的数字最大数字表示。 (还要小心浮点数。因为可表示值之间的差距,它们可能无法表示较高值的数字。)您可能对无符号整数类型有最好的运气。

      这种方法可能过于局限。如果您不想迭代整个数组,您还可以做一些其他事情来加速您的系统。

      使用不同的结构: 字典/地图/树等

      如果您附加到数组,另一种方法可以是布隆过滤器。这将让您知道某个元素是否不在您的集合中,这同样有用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-02
        • 1970-01-01
        相关资源
        最近更新 更多