The title should explain my question.
I have an array:
a = [[1,2],[1,3],[1,4]];
How can I check if the array [1,2] is inside the array a?
That depends on the situation.
given
var a = [1,2], b = [1,3], c = [a,b];
We can check easily if a resides in c, if we have c to test on.
for(var i=0,d;d=c[i];i++) {
if(d === a) {
//a is inside c
}
}
or even simpler for browser that supports it (ie7 doesn't)
if(c.indexOf(a) != -1) {
//a is inside c
}
But if we only have a, and a is not a local variable and we wish to know if it exists inside any array, then we can't, since a is a reference to an object and we can't possibly know if a reference to it exists elsewhere outside our current scope.
if you have a reference, the you can use the == operator. else you have to write your own method to test values. something like this:
function someMethod(testArr, wanted){
for (i=0; i<testArr.length; i++){
if(array_diff(testArr[i], wanted).length==0 && array_diff(wanted, $subArr).length==0){
return true;
}
}
return false;
}
function array_diff(a1, a2)
{
var a=[], diff=[];
for(var i=0;i<a1.length;i++)
a[a1[i]]=true;
for(var i=0;i<a2.length;i++)
if(a[a2[i]]) delete a[a2[i]];
else a[a2[i]]=true;
for(var k in a)
diff.push(k);
return diff;
}
If your array contains numbers or texts only, you can join each array into string, then compare if a string is inside the other.
var a = [[1,2],[1,3],[1,4]];
var b = [1,2]
var aStr = '#' + a.join('#') + '#'
var bStr = '#' + b.join() + '#'
if (aStr.indexOf(bStr) > -1){
alert ('b is inside a')
}else{
alert ('b is not inside a')
}
You can try this if your array elements are non-nested arrays.
return JSON.stringify([[1,2],[1,3],[1,4]]).indexOf(JSON.stringify([1,2])) > 0
This checks if the JSON representation of [1,2] is contained in the JSON representation of [[1,2],[1,3],[1,4]]
But in this case it gives a false positive
return JSON.stringify([[[1,2]],[1,3],[1,4]]).indexOf(JSON.stringify([1,2])) > 0
returns true.
You can also loop through the array object and for each of it's item you can use jQuery.isArray() to determine if the object is an array.
Related
I have an array of JSON objects imdb and I want to check if a key exists. I have tried couple different methods but none of them shows the correct result. I looked into this post but doesn't help. Below code
var imdb = [{"123":"hi"}, {"234":"hello"}]; //array of JSON object
var valEventTime = 123; //key I want to find if exists
//approach 1
function getValueByKey(key, data) {
var i, len = data.length;
for (i = 0; i < len; i++) {
if (data[i] && data[i].hasOwnProperty(key)) {
return data[i][key];
}
}
return -1;
}
if(getValueByKey(valEventTime, imdb) > -1){
console.log("Yes");
}
else {
console.log("NOT")
}
//approach 2
if (imdb[valEventTime]) {
console.log("Yes");
} else {
console.log("NOT")
}
//approach 3
var keys=Object.keys(imdb)
for(var i=0;i<keys.length;i++){
if(keys[i]==valEventTime)
{//check your key here
console.log("Yes")
}
else console.log("NOT")
}
The output always shows NOT even though I am searching for a key that already exists (123). Please suggest.
The problem with your solution is that you are trying to search for a integer key where as your json key is a string.
var imdb = [{"123":"hi"}, {"234":"hello"}]; // key is string
var valEventTime = 123; // key is integer
var imdb = [{"123":"hi"}, {"234":"hello"}];
var valEventTime = "123";
var obj = imdb.some((val) => {
return Object.keys(val).includes(valEventTime);
})
console.log(obj);
You can use Array.some() to determine if an array contains a value. For each item you want to use the Array.includes() function to check for your variable for the items return from Object.keys() on each entry. In your example your variable is an integer and the key is a string - you may want to be more specific in your matching.
var imdb = [{"123":"hi"}, {"234":"hello"}];
var valEventTime = "123"; // use a string to match the keys
// use Array.some() to loop through each item and short circuit when we return true
var hasKey = imdb.some(function(movie) {
// get the object keys as an array and see if that array contains your variable
// returning true will also return true from Array.some()
return Object.keys(movie).includes(valEventTime);
});
The code is very simple and I would be expecting true however it returns false
var markets = ["AB", "CD"];
console.log("AB" in markets);
I think you're meaning if (markets.indexOf('AB') !== -1). in essentially checks if the test is a property of the object, not if an element is contained within the array.
For more information, look at Array.indexOf vs. the in operator.
Because in looks up property names, not values. Your property names are the array indices.
From MDN's page on the in operator:
The in operator returns true if the specified property is in the specified object.
prop A string or numeric expression representing a property name or array index
Note a property name or array index. The in operator does not search for property values, but for property names. In this case, the property names are 0 and 1, so 0 in markets will return true.
You should use indexOf, in browsers that support it, and shim it in those that don't.
Because in is meant for objects, not arrays. If you want to reliably do this you have to search through each element in the array:
for( var i=0, l=markets.length; i<l; i++ ){
if( markets[i] === 'AB' ){
// do something
}
}
The following will work, which is what you're thinking:
var markets = { AB: 1, CD: 1 };
console.log( "AB" in markets );
In only works when you are using an object, not an array. So this will work:
var markets = {
AB: 'AB',
CD: 'CD'
};
'AB' in markets; // true
As said in won't help you in this case.
I guess you'll have to write a searching function.
Here's one:
function inArray(ArrObj, Search){
var exists = false;
for (var i = 0; i < ArrObj.length; i++){
if (ArrObj[i] == Search){
return true;
var exists = true;
break;
}
else if ((i == (ArrObj.length - 1)) && (!exists)){
if (ArrObj[i] != Search){
return false;
}
}
}
}
I think you want something like this, console.log(markets[0]);
Possible Duplicate:
Easiest way to find duplicate values in a javascript array
How do I check if an array has duplicate values?
If some elements in the array are the same, then return true. Otherwise, return false.
['hello','goodbye','hey'] //return false because no duplicates exist
['hello','goodbye','hello'] // return true because duplicates exist
Notice I don't care about finding the duplication, only want Boolean result whether arrays contains duplications.
If you have an ES2015 environment (as of this writing: io.js, IE11, Chrome, Firefox, WebKit nightly), then the following will work, and will be fast (viz. O(n)):
function hasDuplicates(array) {
return (new Set(array)).size !== array.length;
}
If you only need string values in the array, the following will work:
function hasDuplicates(array) {
var valuesSoFar = Object.create(null);
for (var i = 0; i < array.length; ++i) {
var value = array[i];
if (value in valuesSoFar) {
return true;
}
valuesSoFar[value] = true;
}
return false;
}
We use a "hash table" valuesSoFar whose keys are the values we've seen in the array so far. We do a lookup using in to see if that value has been spotted already; if so, we bail out of the loop and return true.
If you need a function that works for more than just string values, the following will work, but isn't as performant; it's O(n2) instead of O(n).
function hasDuplicates(array) {
var valuesSoFar = [];
for (var i = 0; i < array.length; ++i) {
var value = array[i];
if (valuesSoFar.indexOf(value) !== -1) {
return true;
}
valuesSoFar.push(value);
}
return false;
}
The difference is simply that we use an array instead of a hash table for valuesSoFar, since JavaScript "hash tables" (i.e. objects) only have string keys. This means we lose the O(1) lookup time of in, instead getting an O(n) lookup time of indexOf.
You could use SET to remove duplicates and compare, If you copy the array into a set it will remove any duplicates. Then simply compare the length of the array to the size of the set.
function hasDuplicates(a) {
const noDups = new Set(a);
return a.length !== noDups.size;
}
One line solutions with ES6
const arr1 = ['hello','goodbye','hey']
const arr2 = ['hello','goodbye','hello']
const hasDuplicates = (arr) => arr.length !== new Set(arr).size;
console.log(hasDuplicates(arr1)) //return false because no duplicates exist
console.log(hasDuplicates(arr2)) //return true because duplicates exist
const s1 = ['hello','goodbye','hey'].some((e, i, arr) => arr.indexOf(e) !== i)
const s2 = ['hello','goodbye','hello'].some((e, i, arr) => arr.indexOf(e) !== i);
console.log(s1) //return false because no duplicates exist
console.log(s2) //return true because duplicates exist
Another approach (also for object/array elements within the array1) could be2:
function chkDuplicates(arr,justCheck){
var len = arr.length, tmp = {}, arrtmp = arr.slice(), dupes = [];
arrtmp.sort();
while(len--){
var val = arrtmp[len];
if (/nul|nan|infini/i.test(String(val))){
val = String(val);
}
if (tmp[JSON.stringify(val)]){
if (justCheck) {return true;}
dupes.push(val);
}
tmp[JSON.stringify(val)] = true;
}
return justCheck ? false : dupes.length ? dupes : null;
}
//usages
chkDuplicates([1,2,3,4,5],true); //=> false
chkDuplicates([1,2,3,4,5,9,10,5,1,2],true); //=> true
chkDuplicates([{a:1,b:2},1,2,3,4,{a:1,b:2},[1,2,3]],true); //=> true
chkDuplicates([null,1,2,3,4,{a:1,b:2},NaN],true); //=> false
chkDuplicates([1,2,3,4,5,1,2]); //=> [1,2]
chkDuplicates([1,2,3,4,5]); //=> null
See also...
1 needs a browser that supports JSON, or a JSON library if not.
2 edit: function can now be used for simple check or to return an array of duplicate values
You can take benefit of indexOf and lastIndexOf. if both indexes are not same, you have duplicate.
function containsDuplicates(a) {
for (let i = 0; i < a.length; i++) {
if (a.indexOf(a[i]) !== a.lastIndexOf(a[i])) {
return true
}
}
return false
}
If you are dealing with simple values, you can use array.some() and indexOf()
for example let's say vals is ["b", "a", "a", "c"]
const allUnique = !vals.some((v, i) => vals.indexOf(v) < i);
some() will return true if any expression returns true. Here we'll iterate values (from the index 0) and call the indexOf() that will return the index of the first occurrence of given item (or -1 if not in the array). If its id is smaller that the current one, there must be at least one same value before it. thus iteration 3 will return true as "a" (at index 2) is first found at index 1.
is just simple, you can use the Array.prototype.every function
function isUnique(arr) {
const isAllUniqueItems = input.every((value, index, arr) => {
return arr.indexOf(value) === index; //check if any duplicate value is in other index
});
return isAllUniqueItems;
}
One nice thing about solutions that use Set is O(1) performance on looking up existing items in a list, rather than having to loop back over it.
One nice thing about solutions that use Some is short-circuiting when the duplicate is found early, so you don't have to continue evaluating the rest of the array when the condition is already met.
One solution that combines both is to incrementally build a set, early terminate if the current element exists in the set, otherwise add it and move on to the next element.
const hasDuplicates = (arr) => {
let set = new Set()
return arr.some(el => {
if (set.has(el)) return true
set.add(el)
})
}
hasDuplicates(["a","b","b"]) // true
hasDuplicates(["a","b","c"]) // false
According to JSBench.me, should preform pretty well for the varried use cases. The set size approach is fastest with no dupes, and checking some + indexOf is fatest with a very early dupe, but this solution performs well in both scenarios, making it a good all-around implementation.
function hasAllUniqueChars( s ){
for(let c=0; c<s.length; c++){
for(let d=c+1; d<s.length; d++){
if((s[c]==s[d])){
return false;
}
}
}
return true;
}
I'm trying to parse some JSON that is sent to me and it's all in the format of
[{key:value},{key2:value2}, ... ]
What would be the best way to get the value of key2 in this? Is there a way to do it without doing a for loop?
You could use the Select function from the Underscore.js library.
Not really, but it wouldn't be hard to create a function to do that. However, it would indeed involves a for loop.
For the sake of completion, that would be the function:
function selectWhere(data, propertyName) {
for (var i = 0; i < data.length; i++) {
if (data[i][propertyName] !== null) return data[i][propertyName];
}
return null;
}
Usage:
var key2value = selectWhere(data, "key2");
Javascript Array comes with methods that do just what you are asking for - find entries without you having to code a for-loop.
You provide them with the condition that you want. A compact and convenient way to do that is with an arrow (or "lambda") function. In your case, you are looking for array entries that have a specific key, so the arrow function could look something like this:
e => e.hasOwnProperty("key2")
Following the lead of some of the others, let's start with the assumption
var arr = [{key:"value"}, {key2:"value2"}, {key3:"value3"}]
If you expect that at most one member of the array has the key you want, you can use the find() function. It will test each array member until it finds one where your condition is true, and return it. If none are true, you'll get undefined.
var foundentry = arr.find(e => e.hasOwnProperty("key2"))
Either foundentry will be undefined or it will be the {key2:"value2"} that you are looking for, and can extract value2 from it.
If arr can have more than one entry with the key that you are looking for, then instead of find() use filter(). It gives back an array of entries that meet your criteria.
var foundarray = arr.filter(e => e.hasOwnProperty("key2"))
jQuery grep() is a good analog for a Where clause:
var array = [{key:1},{key:2}, {key:3}, {key:4}, {key:5}];
var filtered = jQuery.grep(array, function( item, index ) {
return ( item.key !== 4 && index > 1 );
});
Your filtered array will then contain two elements,
[{key:3}, {key:5}]
You can't do it with an array, but you can make an associative array like object with it. Once you make it, you can use it like hash.
var arr = [{key:value},{key2:value2}, ... ], obj = {};
for (var i = 0, len = arr.length; i < len; i++) {
$.extend(obj, arr[i]);
}
console.log(obj.key2); // value2
Here's an example that prototype's the Array object. Note: this is shown for example - find is not a good name for this function, and this probably will not be needed for all arrays
Instead, consider just using the function definition and creating a function like getObjVal, calling like getObjVal(arr,'propName'), similar to LaurenT's answer.
Given
var arr = [{key:'value'},{key2:'value2'}];
Definition
// for-loop example
Array.prototype.find = function (prop){
for(var i=this.length; i--; )
if (typeof this[i][prop] !== 'undefined')
return this[i][prop];
return undefined;
}
// for-each loop example
Array.prototype.find = function (prop){
for (var i in this)
if ( this.hasOwnProperty(i) && typeof this[i][prop] !== "undefined" )
return this[i][prop];
return undefined;
}
Usage
console.log( arr.find('key2') ); // 'value2'
console.log( arr.find('key3') ); // undefined
Use .filter() method for this object array, for example in your case:
var objArray = [{key:"Hello"},{key2:"Welcome"} ];
var key2Value=objArray.filter(x=>x.key2)[0].key2;
Regex - no for loop:
var key2Val = jsonString.match(/\{key2:[^\}]+(?=\})/)[0].substring("{key2:".length);
Top answer does the job. Here's a one liner version of it using lodash (same as underscore for the most part):
var result = _.filter(data, _.partialRight(_.has, 'key2'));
In lodash, select is just an alias for filter. I pass it the data array filled with objects. I use _.has as the the filter function since it does exactly what we want: check if a property exists.
_.has expects two args:
_.has(object, path)
Since _.has expects two arguments, and I know one of them is always constant (the path argument). I use the _.partialRight function to append the constant key2. _.partialRight returns a new function that expects one argument: the object to inspect. The new function checks if obj.key2 exists.
Heyas. You can use the lodash library's .reduce() or .transform() functions to implement this. Lodash is more modular than underscore (Underscore around 5kb, Lodash around 17kb), but is generally lighter because you only include the specific modules you need
(please see: https://news.ycombinator.com/item?id=9078590 for discussion). For this demonstration I will import the entire module (generally not an issue on the backend):
I wrote these snippets for either scenario which handle both numeric and non-numeric arguments.
https://lodash.com/docs#reduce
https://lodash.com/docs#transform
Pull in lodash:
var _ = require('lodash');
_.reduce() to where clause:
var delim = ' WHERE ', where = _.isEmpty(options) ? '' : _.reduce(options, function(r, v, k) {
var w = r + delim + k + '=' + (_.isNumber(v) ? v : ("'" + v + "'"));
delim = ' AND ';
return w;
}, '');
_.transform() to where clause:
var where = _.isEmpty(options) ? '' : ' WHERE ', delim = '';
_.transform(options, function(r, v, k) {
where = where + delim + k + '=' + (_.isNumber(v) ? v : ("'" + v + "'"));
delim = ' AND ';
});
Hope that helps.
Try this:
var parsedJSON = JSON.parse(stringJSON);
var value = parsedJSON['key2'];
I need to check if array contains at least one empty elements. If any of the one element is empty then it will return false.
Example:
var my_arr = new Array();
my_arr[0] = "";
my_arr[1] = " hi ";
my_arr[2] = "";
The 0th and 2nd array elements are "empty".
You can check by looping through the array with a simple for, like this:
function NoneEmpty(arr) {
for(var i=0; i<arr.length; i++) {
if(arr[i] === "") return false;
}
return true;
}
You can give it a try here, the reason we're not using .indexOf() here is lack of support in IE, otherwise it'd be even simpler like this:
function NoneEmpty(arr) {
return arr.indexOf("") === -1;
}
But alas, IE doesn't support this function on arrays, at least not yet.
You have to check in through loop.
function checkArray(my_arr){
for(var i=0;i<my_arr.length;i++){
if(my_arr[i] === "")
return false;
}
return true;
}
You can try jQuery.inArray() function:
return jQuery.inArray("", my_arr)
Using a "higher order function" like filter instead of looping can sometimes make for faster, safer, and more readable code. Here, you could filter the array to remove items that are not the empty string, then check the length of the resultant array.
Basic JavaScript
var my_arr = ["", "hi", ""]
// only keep items that are the empty string
new_arr = my_arr.filter(function(item) {
return item === ""
})
// if filtered array is not empty, there are empty strings
console.log(new_arr);
console.log(new_arr.length === 0);
Modern Javascript: One-liner
var my_arr = ["", "hi", ""]
var result = my_arr.filter(item => item === "").length === 0
console.log(result);
A note about performance
Looping is likely faster in this case, since you can stop looping as soon as you find an empty string. I might still choose to use filter for code succinctness and readability, but either strategy is defensible.
If you needed to loop over all the elements in the array, however-- perhaps to check if every item is the empty string-- filter would likely be much faster than a for loop!
Nowadays we can use Array.includes
my_arr.includes("")
Returns a Boolean
You could do a simple help method for this:
function hasEmptyValues(ary) {
var l = ary.length,
i = 0;
for (i = 0; i < l; i += 1) {
if (!ary[i]) {
return false;
}
}
return true;
}
//check for empty
var isEmpty = hasEmptyValues(myArray);
EDIT: This checks for false, undefined, NaN, null, "" and 0.
EDIT2: Misread the true/false expectation.
..fredrik
function containsEmpty(a) {
return [].concat(a).sort().reverse().pop() === "";
}
alert(containsEmpty(['1','','qwerty','100'])); // true
alert(containsEmpty(['1','2','qwerty','100'])); // false
my_arr.includes("")
This returned undefined instead of a boolean value so here's an alternative.
function checkEmptyString(item){
if (item.trim().length > 0) return false;
else return true;
};
function checkIfArrayContainsEmptyString(array) {
const containsEmptyString = array.some(checkEmptyString);
return containsEmptyString;
};
console.log(checkIfArrayContainsEmptyString(["","hey","","this","is","my","solution"]))
// *returns true*
console.log(checkIfArrayContainsEmptyString(["yay","it","works"]))
// *returns false*
yourArray.join('').length > 0
Join your array without any space in between and check for its length. If the length, turns out to be greater than zero that means array was not empty. If length is less than or equal to zero, then array was empty.
I see in your comments beneath the question that the code example you give is PHP, so I was wondering if you were actually going for the PHP one? In PHP it would be:
function hasEmpty($array)
{
foreach($array as $bit)
{
if(empty($bit)) return true;
}
return false;
}
Otherwise if you actually did need JavaScript, I refer to Nick Craver's answer
Just do a len(my_arr[i]) == 0; inside a loop to check if string is empty or not.
var containsEmpty = !my_arr.some(function(e){return (!e || 0 === e.length);});
This checks for 0, false, undefined, "" and NaN.
It's also a one liner and works for IE 9 and greater.
One line solution to check if string have empty element
let emptyStrings = strArray.filter(str => str.trim().length <= 0);
let strArray = ['str1', '', 'str2', ' ', 'str3', ' ']
let emptyStrings = strArray.filter(str => str.trim().length <= 0);
console.log(emptyStrings)
One line solution to get non-empty strings from an array
let nonEmptyStrings = strArray.filter(str => str.trim().length > 0);
let strArray = ['str1', '', 'str2', ' ', 'str3', ' ']
let nonEmptyStrings = strArray.filter(str => str.trim().length > 0);
console.log(nonEmptyStrings)
If you only care about empty strings then this will do it:
const arr = ["hi","hello","","jj"]
('' in arr) //returns false
the last line checks if an empty string was found in the array.
I don't know if this is the most performant way, but here's a one liner in ES2015+:
// true if not empty strings
// false if there are empty strings
my_arr.filter(x => x).length === my_arr.length
The .filter(x => x) will return all the elements of the array that are not empty nor undefined. You then compare the length of the original array. If they are different, that means that the array contains empty strings.
You have to check in through the array of some functions.
if isEmptyValue is true that means the array has an empty string otherwise not.
const arr=['A','B','','D'];
const isEmptyValue = arr.some(item => item.trim() === '');
console.log(isEmptyValue)
array.includes("") works just fine.
Let a = ["content1", "" , "content2"];
console.log(a.includes(""));
//Output in console
true