var arr = [{
key: "key1", value: "z"
}, {
key: "key2", value: "u"
}, {
...
}];
How to check whether my key:"key1" exists already or not. If it does not exist, i need to add the key in ma array.
if(arr.hasOwnProperty("key1")){
arr.unshift({key:"key1", value:"z"});
}
To make it easier you should store your data thusly:
var map = {
"key1": "z",
"key2": "u"
};
Then you can do your check and if your keys don't conflict with any existing properties on the object and you don't need null values you can make it easier.
if (!map["key1"]) {
map["key1"] = "z";
}
If you really need the full object (yours is after all just an example), I would store the object as the value of the key, not just store the objects in the array. That is, make it a map, not an array.
Since you've got an Array filled with Objects, you need to do it like:
(ES3)
function lookup( name ) {
for(var i = 0, len = arr.length; i < len; i++) {
if( arr[ i ].key === name )
return true;
}
return false;
}
if( !lookup( 'key1' ) ) {
arr.push({
key: 'key1',
value: 'z'
});
}
You could use the ECMAScript 5 filter method to remove elements from the array if they do not pass your test. If the resulting array has no elements, you know that there were none with your value:
if(!arr.filter(function(elem) {
return elem.key === "key1";
}).length) {
arr.push({ key: "key1", value: "z" });
}
If you want it to work in older browsers you would need to use a shim to make sure Array.prototype.filter is defined.
var key;
for(var i = 0; i < arr.length; i++)
{
if(arr[i].key == "key1")
{
key = arr[i];
break;
}
}
if(typeof (key)=='undefined') //for if the value is 0 as int
{
key = {
key: "key1", value: "aaa"
};
arr.push(key);
}
You can check both arrays and objects to see if an array key or object property exists or not with this. It's very useful, and it is used the same way for checking both types.
/**
* Check if an array key or object property exists
* #key - what value to check for
* #search - an array or object to check in
*/
function key_exists(key, search) {
if (!search || (search.constructor !== Array && search.constructor !== Object)) {
return false;
}
for (var i = 0; i < search.length; i++) {
if (search[i] === key) {
return true;
}
}
return key in search;
}
Usage:
As an array
key_exists('jared', ['jared', 'williams']); //= true
As an object
key_exists('jared', {'jared': 'williams'}); //= true
Below are two, more explicit, versions of #jAndy's accepted answer.
I made the first version for myself so I could understand the logic better and added the following:
if the key does exist, increment the count property of the matched
object, otherwise create a new object with a count of 1.
In the second version, I realised I would prefer my arrayOfObjects variable to be an object, so that later I could specifically target values rather than looping over the array till I got a match, and then getting the relevant object value. So that version uses an object instead of an array of objects.
Version 01 - An array of objects
// based on: https://stackoverflow.com/a/9177103/1063287
// the original array of objects
var arrayofObjects = [{
id: "CY01",
count: 1
},
{
id: "CY33",
count: 5
},
{
id: "CY55",
count: 8
}
];
// show the array in the interface
$(".before").text(JSON.stringify(arrayofObjects));
// define lookup function (must have access to arrayofObjects)
function lookup(key_to_check) {
// for each object in the array of objects
for (var i = 0; i < arrayofObjects.length; i++) {
// if the object key matches the key to check
if (arrayofObjects[i]["id"] === key_to_check) {
// return true with index of matching object
var returnObject = {};
returnObject["exists"] = true;
returnObject["index"] = i;
return returnObject;
}
}
// if the above loop has not already returned a value
// return false
var returnObject = {};
returnObject["exists"] = false;
return returnObject;
}
// on click, check whether the key exists
$(document).on("click", ".run", function() {
var key_to_check = $(".key_to_check").val();
$(".checking").text(key_to_check);
var returnObject = lookup(key_to_check);
// if key to check doesn't exist add it
if (returnObject["exists"] === false) {
console.log("key doesn't exist, adding object");
arrayofObjects.push({
id: key_to_check,
count: 1
});
} else if (returnObject["exists"] === true) {
// else if it does exists, increment the relevant counter
console.log("key does exist, incrementing object count value");
var index = returnObject.index;
arrayofObjects[index].count += 1;
}
$(".after").text(JSON.stringify(arrayofObjects));
});
body {
font-family: arial;
font-size: 14px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>enter an existing or non-existing key and click run.</p>
<p>if existing, increment count, otherwise create new object with count of 1.</p>
<input class="key_to_check"><button class="run">run</button>
<br><br>
<div>array of objects - before: <span class="before"></span> </div>
<div>checking:<span class="checking"></span></div>
<div>array of objects - after: <span class="after"></span></div>
Version 02 - An object
// based on: https://stackoverflow.com/a/9177103/1063287
// the original object
var myObject = {
"CY01": 1,
"CY33": 5,
"CY55": 8
};
// show the object in the interface
$(".before").text(JSON.stringify(myObject));
// define lookup function (must have access to myObject)
function lookup(key_to_check) {
// for each property in the object
for (key in myObject) {
// if the key matches the key to check
if (key === key_to_check) {
// return true
return true
}
}
// if the above loop has not already returned a value
// return false
return false
}
// on click, check whether the key exists
$(document).on("click", ".run", function() {
var key_to_check = $(".key_to_check").val();
$(".checking").text(key_to_check);
var returnObject = lookup(key_to_check);
// if key to check doesn't exist add it
if (returnObject === false) {
console.log("key doesn't exist, adding object");
myObject[key_to_check] = 1;
} else if (returnObject === true) {
// else if it does exists, increment the relevant counter
console.log("key does exist, incrementing object count value");
myObject[key_to_check] += 1;
}
$(".after").text(JSON.stringify(myObject));
});
body {
font-family: arial;
font-size: 14px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>enter an existing or non-existing key and click run.</p>
<p>if existing, increment count, otherwise create new property with count of 1.</p>
<input class="key_to_check"><button class="run">run</button>
<br><br>
<div>my object - before: <span class="before"></span> </div>
<div>checking:<span class="checking"></span></div>
<div>my object - after: <span class="after"></span></div>
Related
I have an object which contains alot of keys and values. I can get any value using the index. But I dont have the full index, I have a part of it, would I be able to get the value based on a part of the index.
Example:
c = {'select':'MyValue',...}
I can get the value using indexing as shown below:
c['select'] = 'MyValue'
I tried to create this function which searches exact value:
function search(nameKey, c){
for (var i=0; i < c.length; i++) {
if (c[i].select === nameKey) {
return c[i];
}
}
}
c['select'] will return 'MyValue' but I need to do something like c['Sel'] or c['select'] or c['Select']or c['selected']to return the same 'MyValue'
Well the logic doesn't seem to be very clear and it's not quite relevant how it would be matching the key.
But This is a function that may help in the specific cases you showed:
function search(nameKey, obj) {
if (obj.hasOwnProperty(nameKey)) {
return obj[nameKey];
} else {
var res = Object.keys(obj).filter(function(k) {
return (k.toLowerCase().indexOf(nameKey.toLowerCase()) > -1) || (nameKey.toLowerCase().indexOf(k.toLowerCase()) > -1);
});
return res ? obj[res] : false;
}
}
Explanation:
First we use Object#hasOwnProperty() to check if the object has the searched name as key/property, we return it's value, this will avoid looping all the keys.
Otherwise we use Object.keys() to get the keys of the object.
Then we use Array#filter() method over the keys array to check if a relevant key exists we
return it's value, otherwise we return false.
Demo:
function search(nameKey, obj) {
if (obj.hasOwnProperty(nameKey)) {
return obj[nameKey];
} else {
var res = Object.keys(obj).filter(function(k) {
return (k.toLowerCase().indexOf(nameKey.toLowerCase()) > -1) || (nameKey.toLowerCase().indexOf(k.toLowerCase()) > -1);
});
return res ? obj[res] : false;
}
}
var c = {
'select': 'MyValue'
};
console.log(search("Sel", c));
Here's an one liner (!):
Assuming your array is in data and the partial index value is in selector:
const result = Object.keys(data).filter(k => k.toLowerCase().indexOf(selector.toLowerCase()) != -1).map(k => data[k]);
The above code returns an Array (coz, there may be more than one match). If you just need a first element, just do result[0].
You can use Object.keys() to get an array of the property names.
Then find first match using Array#find() to get the key needed (if it exists)
const data = {
aaaa: 1,
bbbbbbb: 2,
cccc: 3
}
function search(nameKey, obj) {
nameKey = nameKey.toLowerCase();// normalize both to lowercase to make it case insensitive
const keys = Object.keys(obj);
const wantedKey = keys.find(key => key.toLowerCase().includes(nameKey));
return wantedKey ? obj[wantedKey] : false;
}
console.log('Term "a" value:', search('a',data))
console.log('Term "bb" value:', search('bb',data))
console.log('Term "X" value:', search('X',data))
Since search criteria is vague I simply found any match anywhere in the property name and didn't look past the first one found
Im trying to get indexOf of a object after its pushed inside a array.
This is not returning the same value back as i do indexOf whenever objext is allready in the array.
SCENARIO
var arr = [];
setInterval(function() {
var path = { one: "f00"};
if (typeof path !== "undefined") {
if (arr.indexOf(path) === -1) {
console.log("Not Exists!!")
arr.push(path)
} else {
console.log("Exists!!")
}
}
console.log(arr)
}, 2000)
What is the different between the working of
The issue is that JavaScript doesn't do a deep compare of objects, so it doesn't recognize them as the same.
var a = { name: 'foo' }
var b = { name: 'foo' }
a === b // false
However, since you have access to the object before the insert, you can save a reference to it, and then search for that reference:
var arr = []
var obj = { path: 'foo' }
arr.push(obj)
arr.indexOf(obj) // 0
This is because indexOf uses the strict equality === comparison. So in this case, the references to obj and the object at arr[0] are the same.
Edit
Based on your changed question, here is a way to write your function to do what you want:
var arr = [];
function findAdnSet(obj) {
var index = arr.indexOf(obj);
if (index !== -1) {
return index;
} else {
arr.push(obj);
return arr.length - 1; // No reason to use indexOf here, you know the location since you pushed it, meaning it HAS to be the last element in the array
}
}
var path = { name: 'foo' };
findAndSet(path);
A more robust option than using indexOf since your function might not always have a good reference available is to use find/findIndex:
var arr = [];
function findAndSet(obj) {
var index = arr.findIndex(function(item) {
if (item.name === 'foo') {
return true;
}
});
if (index) { // findIndex returns `undefined` if nothing is found, not -1
return index;
} else {
arr.push(obj);
return arr.length - 1;
}
}
// You don't need a reference anymore since our method is doing a "deep" compare of the objects
findAndSet({ name: 'foo' });
The first time you do indexOf you push and search for the object 'path' so it is found. The second time you create an object and add push it to the array, and then search for another new object (which happens to have the same values), but since it is not the same object that you pushed it is not found.
I am working on a function where I pass an object (record) to a function. It then loops over the keys and checks to see if that key is in our second object (lookup). If there is a match, it replaces the value in our record with a manipulated version (turns it into a link). If there is no match, it keeps its original value.
This is what I am passing to the function:
{ Source: "1234", NTID: "joeBob", Department: "x123", Email: 'joebob#example.com' }
-Here is the function
function createLink2(record) {
// Link types
var output = {
'ntid': 'https://example.com/profile/',
'email': 'mailTo:'
};
// Vars
var i,
key,
keys = Object.keys(output);
// Loop over our object keys
Object.keys(record).forEach(function(k, ind) {
// Loop over each of the link types
for ( i = 0; i < keys.length; ++i ) {
key = keys[i];
// If our key matches that of our object, turn it into a link
if(k.toLowerCase() == key){
record = ''+record[k]+'';
}else{
// Return the original value of the property since its not a match. Not quite sure how to do this part.
}
}
});
return record;
}
My goal here is that it would replace the value of Email with joeBob#example.com and NTID with joeBob.
The issue I am having is with the return - Not quite sure how to edit the data and return the full object back.
change this line:
record = ''+record[k]+'';
to this:
record[k] = ''+record[k]+'';
Of course, you could do this more easily by referring to the properties of the object directly:
function createLink2(record) {
// Link types
var output = {
'NTID': 'https://example.com/profile/',
'Email': 'mailTo:'
};
// Loop over the output keys
Object.keys(output).forEach(function(k, ind) {
if(record.hasOwnProperty(k)) {
record[k] = '' + record[k] + '';
}
});
return record;
}
Note that you don't really need to return it since the contents of the object will be changed directly as mentioned by others in the comments.
Javascript objects are passed by reference. So if you modify the object in the function it will be enough. Example:
function test(obj) {
obj.a = 10
}
var x = {a: 2};
test(x);
console.log(x.a) //prints 10
So, all you have to do is modify the value of "Email" with whatever you want.
You can iterate over an array and return an object using .reduce()
function createLink2(record) {
// Link types
var output = {
'ntid': 'https://example.com/profile/',
'email': 'mailTo:'
};
// Vars
var keys = Object.keys(output);
// Loop over our object keys
record = keys.reduce(function(obj, currKey) {
if (obj[currKey] != undefined) {
obj[currKey] = '' + obj[currKey] + ''
}
return obj;
}, record);
return record;
}
console.log(createLink2({ntid: "12345", email: "joebob#gmail.com"}));
I'm building an application which involves the creation of an array of objects, similar to this:
var foo = [{
'foo' : 'foo1'
},
{
'foo' : 'foo2'
},
{
'foo' : 'foo3'
}];
there's then an HTML form where the user fills in the values for new objects. When the form is submitted the new values are pushed to the array. what I want is an if/else statement which checks if the new object already exists in the array.
So something like:
document.getElementById('form').addEventListener('submit',function(){
var newObject = {'foo' : input value goes here }
if (//Checks that newObject doesn't already exist in the array) {
foo.push(newObject)
}
else {
//do nothing
}
});
It's also probably worth noting that I'm using Angular
You can use this approach:
You need:
Understand how to compare 2 objects.
Do it in cycle.
How to compare 2 objects.
One of the ways is:
JSON.stringify(obj1) === JSON.stringify(obj2)
Note, that comparing ojbects this way is not good:
Serializing objects merely to compare is terribly expensive and not
guaranteed to be reliable
As cookie monster mentioned in comments to this post.
I just suggested it, to achieve what you want. You can find better variant. You can find some beautiful answers here.
How to do it in cycle :D
In your case it will be:
function checkIfObjectExists(array, newObject) {
var i = 0;
for(i = 0; i < array.length; i++ ) {
var object = array[i];
if(JSON.stringify(object) === JSON.stringify(newObject))
{
return true;
}
}
return false;
}
Also, I added function, so you can use it in your code.
Now add this to your code:
if (checkIfObjectExists(foo, newObject)) {
// objects exists, do nothing
}
else {
foo.push(newObject);
}
DEMO
You'd have to loop through the foo-array and check for any duplicates.
document.getElementById('form').addEventListener('submit',function(){
var newObject = {'foo' : input value goes here }
if (!isInArray(foo, newObject, 'foo')) {
foo.push(newObject)
}
});
function isInArray(arr, newObj, type) {
var i, tempObj, result = false;
for (i = 0; i < arr.length; i += 1) {
tempObj = arr[i];
if (tempObj[type] === newObj[type]) {
result = true;
}
}
return result;
}
It's easier and faster if your array doesn't contain objects. Then you simply can make the if-clause to be:
document.getElementById('form').addEventListener('submit',function(){
var newString = "foo bar";
if (foo.indexOf(newString) === -1) {
foo.push(newString);
}
});
I am having a array as follows
var nameIDHashMap = [];
nameIDHashMap.push({
key: name,
value: xmlLength
});
startToEnd.push({
key: $(this).attr("startFrom"),
value: $(this).attr("endTo")
});
I m trying to use the inArray() function like shown below
var variablestart = startToEnd[0].key;
alert("The variable Start is :"+variablestart);
var toEnd;
if(jQuery.inArray(variablestart,nameIDHashMap) > -1) {
alert('found');
}
if ($.inArray(variablestart, nameIDHashMap) != -1)
{
alert("Found");
// toEnd = startToEnd[connectWindow].value
}
else
alert("Fail");
I dont know why always the else loop is called. None of the if loop is getting called. Both of the array has that same key present. Please let me know where I am doing wrong.Thanks!
variablestart is a property of an element in the array, not an element in the array.
var nameIDHashMap = [];
nameIDHashMap.push({
key: 'foo',
value: 'bar'
});
$.inArray(nameIDHashMap[0].key, nameIDHashMap); // this is not an element, -1
$.inArray(nameIDHashMap[0], nameIDHashMap); // this is an element, 0
You are essentially trying to equate the object { key: 'foo', value: 'bar' } to the string 'foo', which are not equal.
http://jsfiddle.net/jbabey/kgYSe/
That's not how .inArray() works. It searches for an array element that's equal to the value you pass in. It doesn't have any provisions for a comparison function.
Even if it did work, what you're assembling there isn't a "hash table". If you want to do efficient lookups by key, you can just create named properties on a simple object:
var map = {};
map.someKey = someValue;
The .inArray() method and anything like it performs a linear-time search through the array, and that's not a very efficient way to do things if you're going to have an "interesting" number of key/value pairs.
edit — if you really must keep a linear unindexed list of named properties, you could use a lookup function like this:
function find( list, key, test ) {
test = test || function(e) { return e ? e.key == key : false; };
for (var i = 0; i < list.length; ++i)
if (test(list[i])) return i;
return -1;
}
To use that, you'd just do:
if (find(nameIDHashMap, someKey) >= 0) {
alert("Found!");
}