找出 JavaScript 数组是否包含值的最简洁有效的方法是什么?
这是我知道的唯一方法:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
}
有没有更好更简洁的方法来实现这一点?
找出 JavaScript 数组是否包含值的最简洁有效的方法是什么?
这是我知道的唯一方法:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
}
有没有更好更简洁的方法来实现这一点?
现代浏览器有Array#includes
,它正是这样做的,并且得到了除 IE 之外的所有人的广泛支持:
console.log(['joe', 'jane', 'mary'].includes('jane')); //true
您也可以使用Array#indexOf
,它不那么直接,但对于过时的浏览器不需要 polyfill。
console.log(['joe', 'jane', 'mary'].indexOf('jane') >= 0); //true
许多框架也提供了类似的方法:
$.inArray(value, array, [fromIndex])
_.contains(array, value)
也别名为_.include
and _.includes
)dojo.indexOf(array, value, [fromIndex, findLast])
array.indexOf(value)
array.indexOf(value)
findValue(array, value)
array.indexOf(value)
Ext.Array.contains(array, value)
_.includes(array, value, [from])
是_.contains
4.0.0 之前的版本)R.includes(value, array)
请注意,一些框架将其实现为一个函数,而另一些框架则将该函数添加到数组原型中。
2019 年更新:此答案来自 2008 年(11 岁!),与现代 JS 使用无关。承诺的性能改进是基于当时在浏览器中完成的基准测试。它可能与现代 JS 执行上下文无关。如果您需要一个简单的解决方案,请寻找其他答案。如果您需要最佳性能,请在相关执行环境中为自己进行基准测试。
正如其他人所说,通过数组进行迭代可能是最好的方式,但已经证明递减while
循环是 JavaScript 中最快的迭代方式。所以你可能想重写你的代码如下:
function contains(a, obj) {
var i = a.length;
while (i--) {
if (a[i] === obj) {
return true;
}
}
return false;
}
当然,你也可以扩展 Array 原型:
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] === obj) {
return true;
}
}
return false;
}
现在您可以简单地使用以下内容:
alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false
indexOf
也许吧,但它是“ECMA-262 标准的 JavaScript 扩展;因此它可能不会出现在该标准的其他实现中。”
例子:
[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1
AFAICS Microsoft 没有为此提供某种替代方案,但indexOf
如果您愿意,您可以在 Internet Explorer(以及其他不支持)。
最重要的答案假定原始类型,但如果你想知道一个数组是否包含一个具有某种特征的对象, Array.prototype.some()是一个优雅的解决方案:
const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]
items.some(item => item.a === '3') // returns true
items.some(item => item.a === '4') // returns false
它的好处是一旦找到元素就会中止迭代,这样就可以避免不必要的迭代周期。
此外,它非常适合if
语句,因为它返回一个布尔值:
if (items.some(item => item.a === '3')) {
// do something
}
* 正如 jamess 在评论中指出的那样,在 2018 年 9 月给出这个答案时,Array.prototype.some()
完全支持:caniuse.com 支持表
ECMAScript 7 引入了Array.prototype.includes
.
它可以这样使用:
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
它还接受可选的第二个参数fromIndex
:
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
与indexOf
使用Strict Equality Comparison的不同,includes
使用SameValueZero相等算法进行比较。这意味着您可以检测数组是否包含NaN
:
[1, 2, NaN].includes(NaN); // true
也不同于indexOf
,includes
不会跳过缺失的索引:
new Array(5).includes(undefined); // true
目前它仍然是一个草稿,但可以通过polyfill使其适用于所有浏览器。
假设您已经定义了一个这样的数组:
const array = [1, 2, 3, 4]
以下是检查是否有a的三种方法3
。它们都返回true
或false
。
array.includes(3) // true
// Prefixing the method with '_' to avoid name clashes
Object.defineProperty(Array.prototype, '_includes', { value: function (v) { return this.indexOf(v) !== -1 }})
array._includes(3) // true
const includes = (a, v) => a.indexOf(v) !== -1
includes(array, 3) // true
这是一个与JavaScript 1.6 兼容的实现Array.indexOf
:
if (!Array.indexOf) {
Array.indexOf = [].indexOf ?
function(arr, obj, from) {
return arr.indexOf(obj, from);
} :
function(arr, obj, from) { // (for IE6)
var l = arr.length,
i = from ? parseInt((1 * from) + (from < 0 ? l : 0), 10) : 0;
i = i < 0 ? 0 : i;
for (; i < l; i++) {
if (i in arr && arr[i] === obj) {
return i;
}
}
return -1;
};
}
采用:
function isInArray(array, search)
{
return array.indexOf(search) >= 0;
}
// Usage
if(isInArray(my_array, "my_value"))
{
//...
}
扩展 JavaScriptArray
对象是一个非常糟糕的主意,因为您将新属性(您的自定义方法)引入for-in
可能会破坏现有脚本的循环中。几年前,Prototype库的作者不得不重新设计他们的库实现以删除这种东西。
如果您不需要担心与页面上运行的其他 JavaScript 的兼容性,那就去吧,否则,我会推荐更笨拙但更安全的独立函数解决方案。
今天 2020.01.07 我在 Chrome v78.0.0、Safari v13.0.4 和 Firefox v71.0.0 上对 MacOs HighSierra 10.13.6 进行了 15 种选定解决方案的测试。结论
JSON
,Set
并且令人惊讶的是find
(K,N,O) 的解决方案在所有浏览器上都是最慢的includes
(F) 仅在 chrome 上速度很快for
(C,D) 和indexOf
(G,H) 的解决方案在小型和大型阵列上的所有浏览器上都非常快,因此它们可能是有效解决方案的最佳选择for
(C,D,E) 的解决方案给出了类似的结果(~630 ops/sec - 但 safari 和 firefox 上的 E 为 10-比 C 和 D 慢 20%)我执行 2 个测试用例:对于具有 10 个元素的数组和具有 100 万个元素的数组。在这两种情况下,我们都将搜索到的元素放在数组中间。
let log = (name,f) => console.log(`${name}: 3-${f(arr,'s10')} 's7'-${f(arr,'s7')} 6-${f(arr,6)} 's3'-${f(arr,'s3')}`)
let arr = [1,2,3,4,5,'s6','s7','s8','s9','s10'];
//arr = new Array(1000000).fill(123); arr[500000]=7;
function A(a, val) {
var i = -1;
var n = a.length;
while (i++<n) {
if (a[i] === val) {
return true;
}
}
return false;
}
function B(a, val) {
var i = a.length;
while (i--) {
if (a[i] === val) {
return true;
}
}
return false;
}
function C(a, val) {
for (var i = 0; i < a.length; i++) {
if (a[i] === val) return true;
}
return false;
}
function D(a,val)
{
var len = a.length;
for(var i = 0 ; i < len;i++)
{
if(a[i] === val) return true;
}
return false;
}
function E(a, val){
var n = a.length-1;
var t = n/2;
for (var i = 0; i <= t; i++) {
if (a[i] === val || a[n-i] === val) return true;
}
return false;
}
function F(a,val) {
return a.includes(val);
}
function G(a,val) {
return a.indexOf(val)>=0;
}
function H(a,val) {
return !!~a.indexOf(val);
}
function I(a, val) {
return a.findIndex(x=> x==val)>=0;
}
function J(a,val) {
return a.some(x=> x===val);
}
function K(a, val) {
const s = JSON.stringify(val);
return a.some(x => JSON.stringify(x) === s);
}
function L(a,val) {
return !a.every(x=> x!==val);
}
function M(a, val) {
return !!a.find(x=> x==val);
}
function N(a,val) {
return a.filter(x=>x===val).length > 0;
}
function O(a, val) {
return new Set(a).has(val);
}
log('A',A);
log('B',B);
log('C',C);
log('D',D);
log('E',E);
log('F',F);
log('G',G);
log('H',H);
log('I',I);
log('J',J);
log('K',K);
log('L',L);
log('M',M);
log('N',N);
log('O',O);
This shippet only presents functions used in performance tests - it not perform tests itself!
小数组 - 10 个元素
您可以在您的机器上执行测试这里
大数组 - 1.000.000 个元素
您可以在您的机器上执行测试这里
单线:
function contains(arr, x) {
return arr.filter(function(elem) { return elem == x }).length > 0;
}
开箱即用,如果您多次多次进行此调用,则使用关联数组和 Map 使用散列函数进行查找会效率更高。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
我使用以下内容:
Array.prototype.contains = function (v) {
return this.indexOf(v) > -1;
}
var a = [ 'foo', 'bar' ];
a.contains('foo'); // true
a.contains('fox'); // false
function contains(a, obj) {
return a.some(function(element){return element == obj;})
}
Array.prototype.some()在第 5 版中被添加到 ECMA-262 标准中
如果您使用 JavaScript 1.6 或更高版本(Firefox 1.5 或更高版本),则可以使用Array.indexOf。否则,我认为您最终会得到类似于原始代码的内容。
希望更快的双向indexOf
/lastIndexOf
替代方案
虽然新方法包含非常好,但目前支持基本上为零。
很长时间以来,我一直在想办法替换缓慢的 indexOf/lastIndexOf 函数。
已经找到了一种高效的方法,查看最重要的答案。从那些我选择了contains
@Damir Zekic 发布的函数中,它应该是最快的。但它也指出,基准是从 2008 年开始的,因此已经过时。
我也更喜欢while
,for
但不是出于特定原因,我结束了用 for 循环编写函数。也可以使用while --
.
如果我在执行过程中检查数组的两侧,我很好奇迭代是否会慢得多。显然没有,所以这个函数比投票最多的函数快两倍左右。显然它也比原生的更快。这是在现实世界环境中,您永远不知道您正在搜索的值是在数组的开头还是结尾。
当您知道您刚刚推送了一个带有值的数组时,使用 lastIndexOf 可能仍然是最好的解决方案,但是如果您必须遍历大数组并且结果可能无处不在,这可能是使事情变得更快的可靠解决方案。
双向 indexOf/lastIndexOf
function bidirectionalIndexOf(a, b, c, d, e){
for(c=a.length,d=c*1; c--; ){
if(a[c]==b) return c; //or this[c]===b
if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
}
return -1
}
//Usage
bidirectionalIndexOf(array,'value');
http://jsperf.com/bidirectionalindexof
作为测试,我创建了一个包含 100k 条目的数组。
三个查询:在数组的开头、中间和结尾。
我希望你也觉得这很有趣并测试性能。
注意:如您所见,我稍微修改了函数以contains
反映 indexOf 和 lastIndexOf 输出(基本上true
使用index
and )。那不应该伤害它。false
-1
Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
for(c=this.length,d=c*1; c--; ){
if(this[c]==b) return c; //or this[c]===b
if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
}
return -1
},writable:false, enumerable:false});
// Usage
array.bidirectionalIndexOf('value');
该函数也可以很容易地修改为返回真或假,甚至返回对象、字符串或其他任何东西。
这是while
变体:
function bidirectionalIndexOf(a, b, c, d){
c=a.length; d=c-1;
while(c--){
if(b===a[c]) return c;
if(b===a[d-c]) return d-c;
}
return c
}
// Usage
bidirectionalIndexOf(array,'value');
我认为在数组中获取反射索引的简单计算非常简单,它比执行实际循环迭代快两倍。
这是一个复杂的示例,每次迭代执行三项检查,但这只有通过更长的计算才能实现,这会导致代码变慢。
function inArray(elem,array)
{
var len = array.length;
for(var i = 0 ; i < len;i++)
{
if(array[i] == elem){return i;}
}
return -1;
}
如果找到则返回数组索引,如果未找到则返回 -1
我们使用这个片段(适用于对象、数组、字符串):
/*
* @function
* @name Object.prototype.inArray
* @description Extend Object prototype within inArray function
*
* @param {mix} needle - Search-able needle
* @param {bool} searchInKey - Search needle in keys?
*
*/
Object.defineProperty(Object.prototype, 'inArray',{
value: function(needle, searchInKey){
var object = this;
if( Object.prototype.toString.call(needle) === '[object Object]' ||
Object.prototype.toString.call(needle) === '[object Array]'){
needle = JSON.stringify(needle);
}
return Object.keys(object).some(function(key){
var value = object[key];
if( Object.prototype.toString.call(value) === '[object Object]' ||
Object.prototype.toString.call(value) === '[object Array]'){
value = JSON.stringify(value);
}
if(searchInKey){
if(value === needle || key === needle){
return true;
}
}else{
if(value === needle){
return true;
}
}
});
},
writable: true,
configurable: true,
enumerable: false
});
用法:
var a = {one: "first", two: "second", foo: {three: "third"}};
a.inArray("first"); //true
a.inArray("foo"); //false
a.inArray("foo", true); //true - search by keys
a.inArray({three: "third"}); //true
var b = ["one", "two", "three", "four", {foo: 'val'}];
b.inArray("one"); //true
b.inArray('foo'); //false
b.inArray({foo: 'val'}) //true
b.inArray("{foo: 'val'}") //false
var c = "String";
c.inArray("S"); //true
c.inArray("s"); //false
c.inArray("2", true); //true
c.inArray("20", true); //false
如果您反复检查数组中是否存在对象,您可能应该查看
contains(a, obj)
.适用于所有现代浏览器的解决方案:
function contains(arr, obj) {
const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
return arr.some(item => JSON.stringify(item) === stringifiedObj);
}
用法:
contains([{a: 1}, {a: 2}], {a: 1}); // true
IE6+解决方案:
function contains(arr, obj) {
var stringifiedObj = JSON.stringify(obj)
return arr.some(function (item) {
return JSON.stringify(item) === stringifiedObj;
});
}
// .some polyfill, not needed for IE9+
if (!('some' in Array.prototype)) {
Array.prototype.some = function (tester, that /*opt*/) {
for (var i = 0, n = this.length; i < n; i++) {
if (i in this && tester.call(that, this[i], i, this)) return true;
} return false;
};
}
用法:
contains([{a: 1}, {a: 2}], {a: 1}); // true
JSON.stringify
?Array.indexOf
并且Array.includes
(以及此处的大多数答案)仅按参考而不是按价值进行比较。
[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object
未优化的 ES6 单行:
[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true
注意:如果键的顺序相同,按值比较对象会更好,所以为了安全起见,您可以先使用如下包对键进行排序:https ://www.npmjs.com/package/sort-keys
contains
使用性能优化更新了功能。感谢itinance指出。
使用 lodash 的一些功能。
它简洁,准确,并具有出色的跨平台支持。
接受的答案甚至不符合要求。
要求:推荐最简洁有效的方法来判断一个 JavaScript 数组是否包含一个对象。
接受的答案:
$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1
我的建议:
_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true
笔记:
$.inArray 可以很好地确定标量值是否存在于标量数组中...
$.inArray(2, [1,2])
> 1
...但问题显然要求一种有效的方法来确定对象是否包含在数组中。
为了同时处理标量和对象,您可以这样做:
(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)
虽然array.indexOf(x)!=-1
这是最简洁的方法(并且已经被非 Internet Explorer 浏览器支持了十多年......),但它不是 O(1),而是 O(N),这很糟糕。如果您的数组不会改变,您可以将数组转换为哈希表,然后执行table[x]!==undefined
or ===undefined
:
Array.prototype.toTable = function() {
var t = {};
this.forEach(function(x){t[x]=true});
return t;
}
演示:
var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})
(不幸的是,虽然您可以创建一个 Array.prototype.contains 来“冻结”一个数组并将一个哈希表存储在 this._cache 中的两行中,但如果您选择稍后编辑您的数组,这将给出错误的结果。JavaScript 没有足够的钩子来让你保持这种状态,不像 Python 例如。)
ECMAScript 6 在 find 上有一个优雅的提议。
find 方法对数组中存在的每个元素执行一次回调函数,直到找到一个回调函数返回真值。如果找到这样的元素,find 立即返回该元素的值。否则,find 返回 undefined。回调仅针对已分配值的数组索引调用;对于已被删除或从未被赋值的索引,它不会被调用。
这是MDN 文档。
查找功能是这样工作的。
function isPrime(element, index, array) {
var start = 2;
while (start <= Math.sqrt(element)) {
if (element % start++ < 1) return false;
}
return (element > 1);
}
console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5
您可以通过定义函数在 ECMAScript 5 及以下版本中使用它。
if (!Array.prototype.find) {
Object.defineProperty(Array.prototype, 'find', {
enumerable: false,
configurable: true,
writable: true,
value: function(predicate) {
if (this == null) {
throw new TypeError('Array.prototype.find called on null or undefined');
}
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
var list = Object(this);
var length = list.length >>> 0;
var thisArg = arguments[1];
var value;
for (var i = 0; i < length; i++) {
if (i in list) {
value = list[i];
if (predicate.call(thisArg, value, i, list)) {
return value;
}
}
}
return undefined;
}
});
}
可以使用具有“has()”方法的Set :
function contains(arr, obj) {
var proxy = new Set(arr);
if (proxy.has(obj))
return true;
else
return false;
}
var arr = ['Happy', 'New', 'Year'];
console.log(contains(arr, 'Happy'));
此要求的简单解决方案是使用find()
如果您有如下对象数组,
var users = [{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "admin"},
{id: "105", name: "user"}];
然后您可以检查具有您的值的对象是否已经存在:
let data = users.find(object => object['id'] === '104');
如果数据为空,则没有管理员,否则它将返回现有对象,例如:
{id: "104", name: "admin"}
然后您可以在数组中找到该对象的索引并使用代码替换该对象:
let indexToUpdate = users.indexOf(data);
let newObject = {id: "104", name: "customer"};
users[indexToUpdate] = newObject;//your new object
console.log(users);
您将获得如下价值:
[{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "customer"},
{id: "105", name: "user"}];
采用:
var myArray = ['yellow', 'orange', 'red'] ;
alert(!!~myArray.indexOf('red')); //true
要确切了解此时tilde
~
该做什么,请参阅此问题波浪号在表达式之前有什么作用?.
好的,你可以优化你的代码来得到结果!
有很多方法可以做到这一点,更干净,更好,但我只是想得到你的模式并将其应用于 using JSON.stringify
,只需在你的情况下做这样的事情:
function contains(a, obj) {
for (var i = 0; i < a.length; i++) {
if (JSON.stringify(a[i]) === JSON.stringify(obj)) {
return true;
}
}
return false;
}
惊讶于这个问题仍然没有添加最新的语法,增加了我的 2 美分。
假设我们有一个对象数组 arrObj,我们想在其中搜索 obj。
数组.原型。indexOf -> (返回index 或 -1)通常用于查找数组中元素的索引。这也可以用于搜索对象,但仅在您传递对同一对象的引用时才有效。
let obj = { name: 'Sumer', age: 36 };
let arrObj = [obj, { name: 'Kishor', age: 46 }, { name: 'Rupen', age: 26 }];
console.log(arrObj.indexOf(obj));// 0
console.log(arrObj.indexOf({ name: 'Sumer', age: 36 })); //-1
console.log([1, 3, 5, 2].indexOf(2)); //3
数组.原型。包括-> (返回true或false)
console.log(arrObj.includes(obj)); //true
console.log(arrObj.includes({ name: 'Sumer', age: 36 })); //false
console.log([1, 3, 5, 2].includes(2)); //true
数组.原型。find ->(接受回调,返回第一个在 CB 中返回 true 的值/对象)。
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }
console.log([1, 3, 5, 2].find(e => e > 2)); //3
数组.原型。findIndex ->(接受回调,返回CB 中返回 true 的第一个值/对象的索引)。
console.log(arrObj.findIndex(e => e.age > 40)); //1
console.log(arrObj.findIndex(e => e.age > 40)); //1
console.log([1, 3, 5, 2].findIndex(e => e > 2)); //1
由于 find 和 findIndex 接受回调,我们可以通过创造性地设置 true 条件从数组中获取任何对象(即使我们没有引用)。
绝不是最好的,但我只是在发挥创造力并添加到曲目中。
Object.defineProperty(Array.prototype, 'exists', {
value: function(element, index) {
var index = index || 0
return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
}
})
// Outputs 1
console.log(['one', 'two'].exists('two'));
// Outputs -1
console.log(['one', 'two'].exists('three'));
console.log(['one', 'two', 'three', 'four'].exists('four'));
它有一个参数:一组对象数。数组中的每个对象都有两个整数属性,分别用 x 和 y 表示。该函数必须返回数组中满足的所有此类对象的计数numbers.x == numbers.y
var numbers = [ { x: 1, y: 1 },
{ x: 2, y: 3 },
{ x: 3, y: 3 },
{ x: 3, y: 4 },
{ x: 4, y: 5 } ];
var count = 0;
var n = numbers.length;
for (var i =0;i<n;i++)
{
if(numbers[i].x==numbers[i].y)
{count+=1;}
}
alert(count);
function countArray(originalArray) {
var compressed = [];
// make a copy of the input array
var copyArray = originalArray.slice(0);
// first loop goes over every element
for (var i = 0; i < originalArray.length; i++) {
var count = 0;
// loop over every element in the copy and see if it's the same
for (var w = 0; w < copyArray.length; w++) {
if (originalArray[i] == copyArray[w]) {
// increase amount of times duplicate is found
count++;
// sets item to undefined
delete copyArray[w];
}
}
if (count > 0) {
var a = new Object();
a.value = originalArray[i];
a.count = count;
compressed.push(a);
}
}
return compressed;
};
// It should go something like this:
var testArray = new Array("dog", "dog", "cat", "buffalo", "wolf", "cat", "tiger", "cat");
var newArray = countArray(testArray);
console.log(newArray);
使用Array.prototype.includes
例如:
const fruits = ['coconut', 'banana', 'apple']
const doesFruitsHaveCoconut = fruits.includes('coconut')// true
console.log(doesFruitsHaveCoconut)
也许从 MDN 阅读此文档:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
下面是Prototype 的做法:
/**
* Array#indexOf(item[, offset = 0]) -> Number
* - item (?): A value that may or may not be in the array.
* - offset (Number): The number of initial items to skip before beginning the
* search.
*
* Returns the position of the first occurrence of `item` within the array — or
* `-1` if `item` doesn't exist in the array.
**/
function indexOf(item, i) {
i || (i = 0);
var length = this.length;
if (i < 0) i = length + i;
for (; i < length; i++)
if (this[i] === item) return i;
return -1;
}
另请参阅此处了解他们如何连接它。
你也可以使用这个技巧:
var arrayContains = function(object) {
return (serverList.filter(function(currentObject) {
if (currentObject === object) {
return currentObject
}
else {
return false;
}
}).length > 0) ? true : false
}
Array.indexOf(Object)
.Array.includes(Object)
.使用 ECMA 6,您可以使用Array.find(FunctionName)
whereFunctionName
是用户定义的函数来搜索数组中的对象。
希望这可以帮助!
使用 indexOf()
您可以使用 indexOf() 方法检查给定值或元素是否存在于数组中。indexOf() 方法如果找到则返回数组内元素的索引,如果未找到则返回 -1。让我们看一下下面的例子:
var fruits = ["Apple", "Banana", "Mango", "Orange", "Papaya"];
var a = "Mango";
checkArray(a, fruits);
function checkArray(a, fruits) {
// Check if a value exists in the fruits array
if (fruits.indexOf(a) !== -1) {
return document.write("true");
} else {
return document.write("false");
}
}
使用 include() 方法
ES6 引入了 includes() 方法来非常容易地执行此任务。但是,此方法仅返回 true 或 false 而不是索引号:
var fruits = ["Apple", "Banana", "Mango", "Orange", "Papaya"];
alert(fruits.includes("Banana")); // Outputs: true
alert(fruits.includes("Coconut")); // Outputs: false
alert(fruits.includes("Orange")); // Outputs: true
alert(fruits.includes("Cherry")); // Outputs: false
采用:
Array.prototype.contains = function(x){
var retVal = -1;
// x is a primitive type
if(["string","number"].indexOf(typeof x)>=0 ){ retVal = this.indexOf(x);}
// x is a function
else if(typeof x =="function") for(var ix in this){
if((this[ix]+"")==(x+"")) retVal = ix;
}
//x is an object...
else {
var sx=JSON.stringify(x);
for(var ix in this){
if(typeof this[ix] =="object" && JSON.stringify(this[ix])==sx) retVal = ix;
}
}
//Return False if -1 else number if numeric otherwise string
return (retVal === -1)?false : ( isNaN(+retVal) ? retVal : +retVal);
}
我知道这不是最好的方法,但由于没有原生的 IComparable 方式来在对象之间进行交互,我想这与比较数组中的两个实体一样接近。此外,扩展 Array 对象可能不是明智之举,但有时也可以(如果您知道它并进行权衡)。
或者这个解决方案:
Array.prototype.includes = function (object) {
return !!+~this.indexOf(object);
};
如果您使用的是 ES6,您可以使用一组:
function arrayHas( array, element ) {
const s = new Set(array);
return s.has(element)
}
这应该比任何其他方法都更高效
我建议使用下划线库,因为它返回值并支持所有浏览器。
var findValue = _.find(array, function(item) {
return item.id == obj.id;
});
将唯一项目添加到另一个列表
searchResults: [
{
name: 'Hello',
artist: 'Selana',
album: 'Riga',
id: 1,
},
{
name: 'Hello;s',
artist: 'Selana G',
album: 'Riga1',
id: 2,
},
{
name: 'Hello2',
artist: 'Selana',
album: 'Riga11',
id: 3,
}
],
playlistTracks: [
{
name: 'Hello',
artist: 'Mamunuus',
album: 'Riga',
id: 4,
},
{
name: 'Hello;s',
artist: 'Mamunuus G',
album: 'Riga1',
id: 2,
},
{
name: 'Hello2',
artist: 'Mamunuus New',
album: 'Riga11',
id: 3,
}
],
playlistName: "New PlayListTrack",
};
}
// Adding an unique track in the playList
addTrack = track => {
if(playlistTracks.find(savedTrack => savedTrack.id === track.id)) {
return;
}
playlistTracks.push(track);
this.setState({
playlistTracks
})
};
正如其他人提到的,您可以使用Array.indexOf
,但并非在所有浏览器中都可用。这是来自https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf的代码,以使其在旧浏览器中的工作方式相同。
indexOf 是 ECMA-262 标准的最新补充;因此,它可能不会出现在所有浏览器中。您可以通过在脚本开头插入以下代码来解决此问题,从而允许在本机不支持它的实现中使用 indexOf。该算法正是 ECMA-262 第 5 版中指定的算法,假设 Object、TypeError、Number、Math.floor、Math.abs 和 Math.max 具有其原始值。
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
"use strict";
if (this == null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (len === 0) {
return -1;
}
var n = 0;
if (arguments.length > 1) {
n = Number(arguments[1]);
if (n != n) { // shortcut for verifying if it's NaN
n = 0;
} else if (n != 0 && n != Infinity && n != -Infinity) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
}
if (n >= len) {
return -1;
}
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
for (; k < len; k++) {
if (k in t && t[k] === searchElement) {
return k;
}
}
return -1;
}
}
使用 idnexOf() 是一个很好的解决方案,但您应该隐藏嵌入式实现 indexOf() 函数,该函数使用 ~ 运算符返回 -1:
function include(arr,obj) {
return !!(~arr.indexOf(obj));
}
我正在做一个项目,我需要一个像 pythonset
这样的功能来删除所有重复值并返回一个新列表,所以我写了这个函数可能对某人有用
function set(arr) {
var res = [];
for (var i = 0; i < arr.length; i++) {
if (res.indexOf(arr[i]) === -1) {
res.push(arr[i]);
}
}
return res;
}
除了其他人所说的之外,如果您没有要在数组中搜索的对象的引用,那么您可以执行类似的操作。
let array = [1, 2, 3, 4, {"key": "value"}];
array.some((element) => JSON.stringify(element) === JSON.stringify({"key": "value"})) // true
array.some((element) => JSON.stringify(element) === JSON.stringify({})) // true
如果任何元素与给定条件匹配,则 Array.some 返回 true,如果没有任何元素与给定条件匹配,则返回 false。
Object.keys
用于获取对象的所有属性名称并过滤与指定字符串完全或部分匹配的所有值。
function filterByValue(array, string) {
return array.filter(o =>
Object.keys(o).some(k => o[k].toLowerCase().includes(string.toLowerCase())));
}
const arrayOfObject = [{
name: 'Paul',
country: 'Canada',
}, {
name: 'Lea',
country: 'Italy',
}, {
name: 'John',
country: 'Italy'
}];
console.log(filterByValue(arrayOfObject, 'lea')); // [{name: 'Lea', country: 'Italy'}]
console.log(filterByValue(arrayOfObject, 'ita')); // [{name: 'Lea', country: 'Italy'}, {name: 'John', country: 'Italy'}]
您还可以按特定键进行过滤,例如。
Object.keys(o).some(k => o.country.toLowerCase().includes(string.toLowerCase())));
现在您可以在过滤后检查数组计数以检查值是否包含。
希望它有帮助。
这可能是一个详细而简单的解决方案。
//plain array
var arr = ['a', 'b', 'c'];
var check = arr.includes('a');
console.log(check); //returns true
if (check)
{
// value exists in array
//write some codes
}
// array with objects
var arr = [
{x:'a', y:'b'},
{x:'p', y:'q'}
];
// if you want to check if x:'p' exists in arr
var check = arr.filter(function (elm){
if (elm.x == 'p')
{
return elm; // returns length = 1 (object exists in array)
}
});
// or y:'q' exists in arr
var check = arr.filter(function (elm){
if (elm.y == 'q')
{
return elm; // returns length = 1 (object exists in array)
}
});
// if you want to check, if the entire object {x:'p', y:'q'} exists in arr
var check = arr.filter(function (elm){
if (elm.x == 'p' && elm.y == 'q')
{
return elm; // returns length = 1 (object exists in array)
}
});
// in all cases
console.log(check.length); // returns 1
if (check.length > 0)
{
// returns true
// object exists in array
//write some codes
}
类似的事情:通过“搜索 lambda”查找第一个元素:
Array.prototype.find = function(search_lambda) {
return this[this.map(search_lambda).indexOf(true)];
};
用法:
[1,3,4,5,8,3,5].find(function(item) { return item % 2 == 0 })
=> 4
在咖啡脚本中相同:
Array.prototype.find = (search_lambda) -> @[@map(search_lambda).indexOf(true)]
我查看了提交的答案,发现它们仅在您通过参考搜索对象时适用。带有参考对象比较的简单线性搜索。
但是假设您没有对对象的引用,您将如何在数组中找到正确的对象?您将不得不对每个对象进行线性和深度比较。想象一下,如果列表太大,并且其中的对象非常大,包含大量文本。性能随着数组中元素的数量和大小而急剧下降。
您可以对对象进行字符串化并将它们放入本机哈希表中,但是您将有数据冗余记住这些键,因为 JavaScript 将它们保留为“for i in obj”,并且您只想检查对象是否存在,即,你有钥匙。
我考虑了一段时间来构建一个 JSON Schema 验证器,我为本地哈希表设计了一个简单的包装器,类似于唯一的哈希表实现,但有一些优化异常,我留给本地哈希表处理。它只需要性能基准测试......所有细节和代码都可以在我的博客上找到: http: //stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a-large-array/ 我将很快发布基准测试结果。
完整的解决方案是这样工作的:
var a = {'a':1,
'b':{'c':[1,2,[3,45],4,5],
'd':{'q':1, 'b':{'q':1, 'b':8},'c':4},
'u':'lol'},
'e':2};
var b = {'a':1,
'b':{'c':[2,3,[1]],
'd':{'q':3,'b':{'b':3}}},
'e':2};
var c = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
var hc = new HashCache([{a:3, b:2, c:5}, {a:15, b:2, c:'foo'}]); //init
hc.put({a:1, b:1});
hc.put({b:1, a:1});
hc.put(true);
hc.put('true');
hc.put(a);
hc.put(c);
hc.put(d);
console.log(hc.exists('true'));
console.log(hc.exists(a));
console.log(hc.exists(c));
console.log(hc.exists({b:1, a:1}));
hc.remove(a);
console.log(hc.exists(c));
检查数组 JavaScript 中是否存在值的最佳默认方法是some()
Array.prototype.some()
该some()
方法测试数组中的至少一个元素是否通过了提供的函数实现的测试。如果在数组中找到所提供函数为其返回 true 的元素,则返回 true;否则返回false。它不会修改数组。
const array = [1, 2, 3, 4, 5];
// checks whether an element is even
const even = (element) => element % 2 === 0;
console.log(array.some(even));
// expected output: true
更多文档Array.prototype.some() - JavaScript | MDN
您也可以使用其他两种方法是find()
和includes()
。使用这些方法,您可以获得结果,但不是最好的。
简单的解决方案:ES6 Features " includes " 方法
let arr = [1, 2, 3, 2, 3, 2, 3, 4];
arr.includes(2) // true
arr.includes(93) // false
使用正则表达式:
console.log(new RegExp('26242').test(['23525', '26242', '25272'].join(''))) // true
有几个选项可以做到这一点,包括includes
, some
, find
, findIndex
。
const array = [1, 2, 3, 4, 5, 6, 7];
console.log(array.includes(3));
//includes() determines whether an array includes a certain value among its entries
console.log(array.some(x => x === 3));
//some() tests if at least one element in the array passes the test implemented by the provided function
console.log(array.find(x => x === 3) ? true : false);
//find() returns the value of the first element in the provided array that satisfies the provided testing function
console.log(array.findIndex(x => x === 3) > -1 ? true : false);
//findIndex() returns the index of the first element in the array that satisfies the provided testing function, else returning -1.
您可以使用 findIndex 函数来检查数组是否具有特定值。
arrObj.findIndex(obj => obj === comparedValue) !== -1;
如果 arrObj 包含 compareValue,则返回 true,否则返回 false。
字面上地:
(使用 Firefox v3.6,for-in
注意事项如前所述(但是,下面的使用可能支持for-in
此目的!也就是说,枚举实际上通过属性索引存在的数组元素(但是,特别是,数组length
属性未在财产for-in
清单!)。)。)
(拖放以下完整 URI 以进行即时模式浏览器测试。)
function ObjInRA(ra){var has=false; for(i in ra){has=true; break;} return has;}
function check(ra){
return ['There is ',ObjInRA(ra)?'an':'NO',' object in [',ra,'].'].join('')
}
alert([
check([{}]), check([]), check([,2,3]),
check(['']), '\t (a null string)', check([,,,])
].join('\n'));
显示:
There is an object in [[object Object]].
There is NO object in [].
There is an object in [,2,3].
There is an object in [].
(a null string)
There is NO object in [,,].
皱纹:如果寻找“特定”对象,请考虑:
JavaScript:alert({}!={}); alert({}!=={});
因此:
obj = {prop:"value"};
ra1 = [obj];
ra2 = [{prop:"value"}];
alert(ra1[0] == obj);
alert(ra2[0] == obj);
通常ra2
被认为是“包含”obj
作为文字实体{prop:"value"}
。
一个非常粗略、基本、幼稚(如代码需要资格增强)的解决方案:
obj={prop:"value"}; ra2=[{prop:"value"}];
alert(
ra2 . toSource() . indexOf( obj.toSource().match(/^.(.*).$/)[1] ) != -1 ?
'found' :
'missing' );
请参阅参考:在 JavaScript 数组中搜索对象。
只是另一种选择
// usage: if ( ['a','b','c','d'].contains('b') ) { ... }
Array.prototype.contains = function(value){
for (var key in this)
if (this[key] === value) return true;
return false;
}
请小心,因为使用自定义方法重载 javascript 数组对象可能会破坏其他 javascript 的行为,从而导致意外行为。