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.
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
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 have a dictionary:
[ object , object, object, object, object ]
object contains: id and name.
I have an Id ('123456') and I want to get the object with this id.
Is there another solution how can I do it without for loop on the objects?
any help appreciated!
Hate loops, then go for recursion, i just assumed that you are having that array in a variable called as xArr
var xObj = check(0,"123456");
function check(cnt,id) {
if(xArr[cnt].id === id)
{
return xArr[cnt];
}
else if(cnt === xArr.length - 1) {
return null;
}
else {
cnt += 1;
return check(cnt, id);
}
}
That's an array, you could use jQuery.grep to get the elements with id "123456".
var result = $.grep(arr, function(obj) {
return obj.id === '123456';
});
Array also provide an .filter method (need a polyfill for browsers not support it):
var result = arr.filter(function(obj) {
return obj.id === '123456';
});
If you want to use a vanilla JS method, you can use filter. This pretty much does the same as $.grep.
var result = arr.filter(function (obj) {
return obj.id === '123456';
});
How would I check in my array of objects, if a specific item exists (in my case MachineId with id 2)?
[{"MachineID":"1","SiteID":"20"},{"MachineID":"2","SiteID":"20"},{"MachineID":"3","SiteID":"20"},{"MachineID":"4","SiteID":"20"}]
I tried this:
if (index instanceof machineIds.MachineID) {
alert('value is Array!');
} else {
alert('Not an array');
}
In cross browser way you may use jQuery.grep() method for it:
var item = $.grep(machineIds, function(item) {
return item.MachineID == index;
});
if (item.length) {
alert("value is Array!");
}
The simplest to understand solution is to loop over the array, and check each one.
var match;
for (var i = 0; i < yourArray.length; i++) {
if (yourArray[i].MachineId == 2)
match = yourArray[i];
}
Note if there is more than one matching item, this will return the last one. You can also dress this up in a function.
function findByMachineId(ary, value) {
var match;
for (var i = 0; i < ary.length; i++) {
if (ary[i].MachineId == value)
match = ary[i];
}
return match;
}
There are many standard solution, you don't need third party libraries or loop iteratively.
Array some method - since JavaScript 1.6.
Array find method - since ES6
Array findIndex method - since ES6
For example, using some();
var yourArray = [{"MachineID":"1","SiteID":"20"},{"MachineID":"2","SiteID":"20"},{"MachineID":"3","SiteID":"20"},{"MachineID":"4","SiteID":"20"}];
var params = {searchedID: "2", elementFound: null};
var isCorrectMachineID = function(element) {
if (element.MachineID == this.searchedID);
return (this.elementFound = element);
return false;
};
var isFound = yourArray.some(isCorrectMachineID, params)
Array some method accepts two parameters:
callback - Function to test for each element.
thisObject - Object to use as this when executing callback.
Callback function is not coupled with the iteration code and, using thisObject parameter, you can even return to the caller the element found or more data.
If such an element is found, some immediately returns true
http://jsfiddle.net/gu8Wq/1/
You could use this condition:
if (arr.filter(function(v){return this.MachineID == 2;}).length > 0)
Old question at this point, but here's an ES6 solution that uses Array.find:
let machine2 = machines.find((machine) => machine.id === '2');
if (machine2) {
// ...
}
var item = [{"MachineID":"1","SiteID":"20"},{"MachineID":"2","SiteID":"20"},{"MachineID":"3","SiteID":"20"},{"MachineID":"4","SiteID":"20"}];
var newItem = item.filter(function(i) {
return i.MachineID == 2; //it will return an object where MachineID matches with 2
});
console.log(newItem); // will print [{"MachineID":"2","SiteID":"20"}]
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!");
}