ChatGPT解决这个技术问题 Extra ChatGPT

查找项目是否在 JavaScript 数组中的最佳方法? [复制]

这个问题在这里已经有了答案:How do I check if an array contains a value in JavaScript? (57 个回答) 5 年前关闭。

查找对象是否在数组中的最佳方法是什么?

这是我知道的最好的方法:

函数 include(arr, obj) { for (var i = 0; i < arr.length; i++) { if (arr[i] == obj) 返回 true; } } console.log(include([1, 2, 3, 4], 3)); // true console.log(include([1, 2, 3, 4], 6)); // 不明确的

两件事: 1.) 'include' 对于一个不修改任何状态的函数来说是一个非常糟糕的名字。对于只返回布尔值的函数来说尤其糟糕。 2.) 您需要添加“return(false);”在函数结束之前。
从 ECMAScript 2016 开始,您可以使用 Array.prototype.includes 函数:myArray.includes(3); // 真的
在 ES6 中,您可以执行类似 arr.find(lamda function) 的操作,例如:[1, 2, 3,4,5].find(x => x == 3)。如果找到元素,则返回否则返回未定义
arr.some(元素 => 元素 === obj); some 是最好的方法,因为当它找到一个项目然后打破循环时。

u
user229044

从 ECMAScript 2016 开始,您可以使用 includes()

arr.includes(obj);

如果要支持 IE 或其他旧版浏览器:

function include(arr,obj) {
    return (arr.indexOf(obj) != -1);
}

编辑:但这不适用于 IE6、7 或 8。如果它不存在,最好的解决方法是自己定义它:

Mozilla 的 (ECMA-262) 版本: if (!Array.prototype.indexOf) { Array.prototype.indexOf = function(searchElement /*, fromIndex */) { "use strict"; if (this === void 0 || this === null) throw new TypeError(); var t = 对象(这个); var len = t.length >>> 0;如果(len === 0)返回-1;变量 n = 0; if (arguments.length > 0) { n = Number(arguments[1]);如果 (n !== n) n = 0;否则 if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) n = (n > 0 || -1) * Math.floor(Math.abs( n));如果 (n >= len) 返回 -1;变量 k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); for (; k < len; k++) { if (k in t && t[k] === searchElement) 返回 k; } 返回 -1; }; } Daniel James 的版本: if (!Array.prototype.indexOf) { Array.prototype.indexOf = function (obj, fromIndex) { if (fromIndex == null) { fromIndex = 0; } else if (fromIndex < 0) { fromIndex = Math.max(0, this.length + fromIndex); } for (var i = fromIndex, j = this.length; i < j; i++) { if (this[i] === obj) return i; } 返回 -1; }; } roosteronacid 的版本: Array.prototype.hasObject = ( !Array.indexOf ? function (o) { var l = this.length + 1; while (l -= 1) { if (this[l - 1] === o ) { return true; } } return false; } : function (o) { return (this.indexOf(o) !== -1); } );


我很好奇为什么您的 Mozilla 功能版本与您链接的网站如此不同。是你自己修改的还是只是旧版本之类的?
@Shenjoku:“2008 年 9 月 27 日 15:45 回答”
嗯,这就是我的答案哈哈。我不能仅通过查看 mozilla 网站来判断是否有旧版本,所以我不确定。不重要,只是好奇。无论如何,这仍然很有帮助,因此您会获得支持;)
@Vinko Vrsalovic 是的,这是一个很好的解决方案,但是您应该隐藏嵌入式实现 indexOf() 函数,该函数使用 ~ 运算符返回 -1: function include(arr,obj) { return !!(~arr.indexOf(obj)) ; }
但是,自从 indexOf 什么时候兼容 IE,因为我发现它兼容 IE w3schools.com/jsref/jsref_indexof.asp
O
Ozgur Vatansever

如果您使用的是 jQuery:

$.inArray(5 + 5, [ "8", "9", "10", 10 + "" ]);

有关详细信息:http://api.jquery.com/jQuery.inArray/


请注意,“inArray”是用词不当,因为它不返回布尔值 - 它返回找到的第一个元素的索引。因此,如果您要检查元素是否存在,您应该使用 if (-1 != $.inArray(...)) ...
有帮助,但我认为这不是一个合适的答案。在我看来,这个问题被标记为“javascript”,表示“香草”。 :)
B
Bill the Lizard

首先,在 JavaScript 中为还没有它的浏览器实现 indexOf。例如,请参阅 Erik Arvidsson's array extras(也称为 associated blog post)。然后您可以使用 indexOf 而不必担心浏览器支持。这是他的 indexOf 实现的稍微优化的版本:

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (obj, fromIndex) {
        if (fromIndex == null) {
            fromIndex = 0;
        } else if (fromIndex < 0) {
            fromIndex = Math.max(0, this.length + fromIndex);
        }
        for (var i = fromIndex, j = this.length; i < j; i++) {
            if (this[i] === obj)
                return i;
        }
        return -1;
    };
}

它已更改为存储长度,因此不需要每次迭代都查找它。但差别不是很大。不太通用的功能可能会更快:

var include = Array.prototype.indexOf ?
    function(arr, obj) { return arr.indexOf(obj) !== -1; } :
    function(arr, obj) {
        for(var i = -1, j = arr.length; ++i < j;)
            if(arr[i] === obj) return true;
        return false;
    };

我更喜欢使用标准功能,并在真正需要时保留这种微优化。但是,如果您热衷于微优化,我将评论中与 roosterononacid 相关的 benchmarks 调整为 benchmark searching in arrays。虽然它们非常粗糙,但完整的调查将测试具有不同类型、不同长度的数组并找到出现在不同位置的对象。


您链接到的代码示例在大型数组上运行缓慢。请参阅我的 hasItem() 函数实现示例中的注释。
看看这些基准:blogs.sun.com/greimer/resource/loop-test.htm For 循环很慢。但我猜基准测试中使用的数组非常庞大:)
我同意。我也很务实。但是在优化语言的基础知识的情况下,我认为实现尽可能高效的功能是一个很好的设计。
使用 mozilla Array.indexOf polyfill:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
a
assortedslog

如果数组未排序,则实际上没有更好的方法(除了使用上面提到的 indexOf,我认为这相当于同一件事)。如果数组已排序,则可以进行二进制搜索,其工作原理如下:

选择数组的中间元素。您正在寻找的元素是否比您选择的元素大?如果是这样,您已经消除了数组的下半部分。如果不是,你已经淘汰了上半部分。选择数组剩余一半的中间元素,并按照步骤 2 继续,消除剩余数组的一半。最终你要么找到你的元素,要么没有数组可以查看。

二分查找的运行时间与数组长度的对数成正比,因此它比查看每个单独的元素要快得多。


您可能应该提到,这种方法在大型排序数组上比小型数组更快。
为什么这在较小的阵列上会变慢?
@vidstige:他的意思是它可以很好地扩展,但对于小输入来说不一定是最快的。
这在 O(lg n) 中运行,而不是 O(n),后者更具可扩展性
b
bortunac

[].has(obj)

假设 .indexOf() 已实现

Object.defineProperty( Array.prototype,'has',
{
    value:function(o, flag){
    if (flag === undefined) {
        return this.indexOf(o) !== -1;
    } else {   // only for raw js object
        for(var v in this) {
            if( JSON.stringify(this[v]) === JSON.stringify(o)) return true;
        }
        return false;                       
    },
    // writable:false,
    // enumerable:false
})

!!!不要创建 Array.prototype.has=function(){...,因为您将在每个数组中添加一个可枚举元素并且 js 已损坏。

//use like          
[22 ,'a', {prop:'x'}].has(12) // false
["a","b"].has("a") //  true

[1,{a:1}].has({a:1},1) // true
[1,{a:1}].has({a:1}) // false

使用第二个参数(标志)强制按值而不是参考进行比较

比较原始对象

[o1].has(o2,true) // true if every level value is same

P
Peter Mortensen

这取决于你的目的。如果您为 Web 编程,请避免使用 indexOf,Internet Explorer 6 不支持它(其中很多仍在使用!),或者有条件地使用:

if (yourArray.indexOf !== undefined) result = yourArray.indexOf(target);
else result = customSlowerSearch(yourArray, target);

indexOf 可能是用本机代码编码的,因此它比您在 JavaScript 中可以执行的任何操作都快(如果数组合适,二进制搜索/二分法除外)。注意:这是一个品味问题,但我会在您的例程结束时执行 return false;,以返回一个真正的布尔值......


哈...我很高兴认为此时仍然有一个 IE6 客户端...
维基百科页面中不应该有一个“截至 2008 年”,这样人们就知道这个声明肯定已经过时了
@allan.simon 看看我答案底部的图标(和统计数据)。就在上面,有“2008 年 9 月 27 日 16:28 回答”。它被称为日期,而习惯于 Stack Overflow 的人们会查看这些日期以含糊其辞……也就是说,我当地的公共图书馆仍然在他们的计算机上安装了 IE6! (但幸运的是,有人安装了 Chrome!)
D
Dan Dascalescu

这是给你的一些元知识 - 如果你想知道你可以用数组做什么,请查看文档 - 这是 Mozilla 的数组页面

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array

在那里你会看到对 indexOf 的引用,它是在 Javascript 1.6 中添加的


包含有关 Javascript 1.8 及更高版本信息的手册的奇怪 URL! :)
这不包括作者询问的对象数组
@VinkoVrsalovic:网址已更改为 developer.mozilla.org/en-US/docs/JavaScript/Reference/…
A
Aaria Carter-Weir

此处详细介绍了一种检查对象是否为 javascript 中的数组的可靠方法:

以下是我附加到 utils = {}“容器”的 xa.js 框架中的两个函数。这些应该可以帮助您正确检测阵列。

var utils = {};

/**
 * utils.isArray
 *
 * Best guess if object is an array.
 */
utils.isArray = function(obj) {
     // do an instanceof check first
     if (obj instanceof Array) {
         return true;
     }
     // then check for obvious falses
     if (typeof obj !== 'object') {
         return false;
     }
     if (utils.type(obj) === 'array') {
         return true;
     }
     return false;
 };

/**
 * utils.type
 *
 * Attempt to ascertain actual object type.
 */
utils.type = function(obj) {
    if (obj === null || typeof obj === 'undefined') {
        return String (obj);
    }
    return Object.prototype.toString.call(obj)
        .replace(/\[object ([a-zA-Z]+)\]/, '$1').toLowerCase();
};

如果您想检查一个对象是否在数组中,我还将包含以下代码:

/**
 * Adding hasOwnProperty method if needed.
 */
if (typeof Object.prototype.hasOwnProperty !== 'function') {
    Object.prototype.hasOwnProperty = function (prop) {
        var type = utils.type(this);
        type = type.charAt(0).toUpperCase() + type.substr(1);
        return this[prop] !== undefined
            && this[prop] !== window[type].prototype[prop];
    };
}

最后是这个 in_array 函数:

function in_array (needle, haystack, strict) {
    var key;

    if (strict) {
        for (key in haystack) {
            if (!haystack.hasOwnProperty[key]) continue;

            if (haystack[key] === needle) {
                return true;
            }
        }
    } else {
        for (key in haystack) {
            if (!haystack.hasOwnProperty[key]) continue;

            if (haystack[key] == needle) {
                return true;
            }
        }
    }

    return false;
}

虽然这在理论上可以回答问题,但it would be preferable在此处包含答案的基本部分,并提供链接以供参考。此外,当您一次复制/粘贴相同的仅链接答案对几个非常古老的问题时,它看起来就像垃圾邮件。
对不起,比尔,我真的不是故意让它看起来像垃圾邮件,只是想更新一些关于这个话题的老问题。我在这里编辑了帖子以包含实际答案,而不是链接。
@Bill,实际上重新阅读了这个问题,这甚至根本没有回答它。我一定犯了一个错误。