creating an array whose elements are javascript objects with a certain property - javascript

I apologize in advance for the very basic question. I have a javascript page on which I create a number of objects, and assign those objects certain properties. What I would like to do is create an array whose elements are all and only those objects which have a certain property. I know how to create (e.g.) an array whose elements are all and only those DOM elements with a certain class; but I can't figure out how to do the parallel thing with javascript objects with a certain property.
I recognize that I could do this manually via an array literal. What I am looking for is a way to generate the array automatically, so that when new javascript objects with the relevant property are added, they are automatically added to the array.
For example, if I have
const firstconstant = {
type: "A",
};
const secondconstant = {
type: "B",
};
const thirdconstant = {
type: "A",
};
etc. I'd like a way of generating an array whose elements are all of the objects with type "A". Thanks for any help with this.

There's no point for declaring a new variable for every new object, that's the reason arrays were invented - so you don't have to type firstconstant, secondconstant, thirdconstant etc.
First declare an array with all the objects (and add them here):
const objects = [
{ type: "A" },
{ type: "B" },
{ type: "A" },
];
And then you can use the .filter method to filter out the objects that don't match:
const filtered = objects.filter(object => object.type === "A");

Related

check if an array "includes" an item in Javascript [duplicate]

This question already has answers here:
Javascript: Using `.includes` to find if an array of objects contains a specific object
(7 answers)
Closed 28 days ago.
I am trying to understand the array "includes" function. My goal is to determine if an array includes a certain item. It works fine for an array of strings but when using objects it doesn't work.
var itemsString = ["name1", "name2"];
var itemsObject = [{ name: "name1" }, { name: "name2" }];
var itemToSearch = { name: "name1" };
console.log(itemsString.includes("name1" ));
console.log(itemsObject.includes(itemToSearch));
console.log(itemsObject.includes(x => x.name === "name1"));
Output:
true
false
false
Does "includes" work with objects or do I need to use another function?
You need to use Array.prototype.some() in this case. Array.prototype.includes() does not accept a function parameter*, and you're not testing for strict equality.
const itemsObject = [{ name: "name1" }, { name: "name2" }];
console.log(itemsObject.some(x => x.name === "name1"));
*Peer pressure from the comments section forces me to clarify that includes() does accept function parameters, but will not use the passed function as a predicate to determine whether a given item matches. Rather, it will try to find an item in the array that is strictly equal to the passed function.
In your last line you check wether a function is inside of your array. .includes also works for objects, but it compares them by reference. In your case you probably want to .find or check wether .some of the objects match your query.
Does "includes" work with objects or do I need to use another
function?
Includes works with objects, but it compares objects by reference.
In your case, despite the first element of itemsObject has the same keys and values of itemToSearch, they are different objects, hence includes will not work, since, for objects cases, it looks for the same object instance.
In order to make it work, you can use several alternatives, like .find, .some, .filter.
Another solution, which I personally don't recommend but I think that it's worth mentioning, is that you can use .includes if you first map items to strings instead. In that case, using JSON.stringify, you can check whether the objects are the same. BEWARE: this will work with single key items only. JSON.stringify doesn't preserve key and values order, so it works with single keys objects only (unless keys and values are in the same order in the original stringified object). Moreover, the JSON.stringify way is way heavier and less performant than the others, I just think it's worth mentioning that as an example.
Below some examples with each of them.
var itemsString = ["name1", "name2"];
var itemsObject = [{ name: "name1" }, { name: "name2" }];
var itemToSearch = { name: "name1" };
console.log(itemsObject.some(r => r.name === itemToSearch.name));
console.log(!!itemsObject.find(r => r.name === itemToSearch.name));
// ^--- !! is used to cast to boolean.
console.log(itemsObject.filter(r => r.name === itemToSearch.name).length > 0);
console.log(itemsObject.map(i => JSON.stringify(i)).includes(JSON.stringify(itemToSearch)));
// ^--------------^ ^---------------------------------------^
// |------ this will stringify each object, converting it to a json string. |
// |
// this will check whether the string[] includes any stringified value.--^

Javascript multiple of the same object within an object

So I need to edit a property of an object in javascript. It contains multiple of the same object name. I am fairly familiar with javascript. My object looks like this:
var object = {
Sub: {
name: "FirstSubName",
propertyToChange: "Keep me the same"
},
Sub: {
name: "SecondSubName",
propertyToChange: "Change me" //This is the property I need to change
}
}
I want to change the second property of the second "Sub" to "ChangedProperty". If I want to do it without using chronological order (like object.Sub[1].propertyToChange = "ChangedProperty", what would I do?
As Bergi said, you cannot have these two properties. What you can have is an array, like this:
var object = {
Sub:[{name: "X", prop: "a property"},{name: "Y", prop: "another prop"}]
}
So, you can access them with the array notation you used in your question or either using a forEach for comparing values, for instance.
Hope this helps.

Best way to find index of exact same object in object Array (key is dynamic)

Let's say I have dynamically loaded object each time with different properties and an array of objects of that type:
var obj = {name: someValue, key: someValue2};
var objArray = [{name: someValue, key: someValue2},{name: someValue, key: someValue3}];
I want to find index of objArray which contains the obj. Some elements of objArray can have the same name property but different key property so searching through obj.name is not an option. So far I came up with this solution:
var keys = [];
_.forEach(Object.keys(obj), function(key) {
keys.push(key, obj[key])
});
var index = _.findIndex(objArray, keys);
This works fine and all but I am looking for something with better performance because this objArray can be very large.
So the question is: Is there a better way to find index of exact same object in object Array?
Update:
I forgot to mention that the names of the keys are not specified and can vary each time.
Use Array.prototype.findIndex(), this works only if you know in advance the property you want to check and hard code the rules in the callback for .findIndex().
An example:
var obj = {
name: 'someValue',
key: 'someValue3'
};
var objArray = [{
name: 'someValue',
key: 'someValue2'
}, {
name: 'someValue',
key: 'someValue3'
}];
var index = objArray.findIndex(function(item, index) {
return (item.name === obj.name) && (item.key === obj.key) ? true : false;
});
console.log('index is: ' + index);
This below it is another approach, basically it takes a JavaScript value (your initial object) and convert to a JSON string, and it uses that string to search within your array. The script works without any recursions, with any number of nested properties for your objects. The order of your property is important in this script, as the conversion to string take it in consideration.
Regarding "best way" is difficult to answer, depending what are your parameters for best way. If you consider performance, you should consider benchmarking your scripts and do test with some real data.
var obj = {
name: 'someValue',
key: 'someValue2'
},
objArray = [{
name: 'someValue',
key: 'someValue2'
}, {
name: 'someValue',
key: 'someValue3'
}];
var str = JSON.stringify(obj),
index = objArray.findIndex(function(item, index) {
return str === JSON.stringify(item) ;
});
console.log('index is: ' + index);
I can think of 2 approaches for doing this:
1.) What would speed up the process (especially if you got large array and large objects) is to create some kind of unique key for every object and map it to let's say property called: hash. If you wanna keep it vanilla, the best way to do that might be using the String.hashCode() method.
Iterate trough object OWN (check hasOwnProperty) properties and concat into single string both property name and then ### and then value and then %%% in between.
Then enhance your object with property hash like:
myObj.hash = String.hashCode(StringOfNamesAndValues);
Now iterate trough your array using for, and compare obj.hash to objArray[index].hash
Once they match you fond your object, store the index :)
If your object and one in the array don't have to be EXACTLY the same object but only a subset needs to be same. Instead using all property names in hash generation, use only the names and values of properties you wanna to be same. Compare hashes made in that way - voila!
2.) More brutish way would be to make object equal function that takes 2 objects and compares all the properties and values of respective properties. Now iterate trough array using that function. Pass your object and array object as parameters. If it returns that comparison is true, store index.
The bigger the objects are the slower this works.The bigger array is the slower this works. The more time you search for same objects slower this works (you compare every time instead making hash once).
Also, if you are having a very large set of object, and search often but add or remove to it sparsely, consider ordering the array in order considering hash values. Then use binary tree search for that hash to find appropriate object instead iterating from start to end each time.

Javascript object/array manipulation

Struggling with some javascript array manipulation/updating. Hope someone could help.
I have an array:
array('saved_designs'=array());
Javascript JSON version:
{"saved_design":{}}
I will be adding a label, and associated array data:
array("saved_designs"=array('label'=array('class'='somecssclass',styles=array(ill add more assoc elements here),'hover'=array(ill add more assoc elements here))))
Javascript version:
{"saved_designs":{"label":{"class":"someclass","style":[],"hover":[]}}}
I want to be able to append/modify this array. If 'label' already defined...then cycle through the sub data for that element...and update. If 'label' doesnt exist..then append a new data set to the 'saved_designs' array element.
So, if label is not defined, add the following to the 'saved_designs' element:
array('label2' = array('class'=>'someclass2',styles=array(),'hover=>array()')
Things arent quite working out as i expect. Im unsure of the javascript notation of [], and {} and the differences.
Probably going to need to discuss this as answers are provided....but heres some code i have at the moment to achive this:
//saveLabel = label the user chose for this "design"
if(isUnique == 0){//update
//ask user if want to overwrite design styles for the specified html element
if (confirm("Their is already a design with that label ("+saveLabel+"). Overwrite this designs data for the given element/styles?")) {
currentDesigns["saved_designs"][saveLabel]["class"] = saveClass;
//edit other subdata here...
}
}else{//create new
var newDesign = [];
newDesign[saveLabel] = [];
newDesign[saveLabel]["class"] = saveClass;
newDesign[saveLabel]["style"] = [];
newDesign[saveLabel]["hover"] = [];
currentDesigns["saved_designs"].push(newDesign);//gives error..push is not defined
}
jQuery("#'.$elementId.'").val(JSON.stringify(currentDesigns));
thanks in advance. Hope this is clear. Ill update accordingly based on questions and comments.
Shaun
It can be a bit confusing. JavaScript objects look a lot like a map or a dictionary from other languages. You can iterate over them and access their properties with object['property_name'].
Thus the difference between a property and a string index doesn't really exist. That looks like php you are creating. It's called an array there, but the fact that you are identifying values by a string means it is going to be serialized into an object in javascript.
var thing = {"saved_designs":{"label":{"class":"someclass","style":[],"hover":[]}}}
thing.saved_designs.label is the same thing as thing["saved_designs"]["label"].
In javascript an array is a list that can only be accessed by integer indices. Arrays don't have explicit keys and can be defined:
var stuff = ['label', 24, anObject]
So you see the error you are getting about 'push not defined' is because you aren't working on an array as far as javascript is concerned.
currentDesigns["saved_designs"] == currentDesigns.saved_designs
When you have an object, and you want a new key/value pair (i.e. property) you don't need a special function to add. Just define the key and the value:
**currentDesigns.saved_designs['key'] = newDesign;**
If you have a different label for every design (which is what it looks like) key is that label (a string).
Also when you were defining the new design this is what javascript interprets:
var newDesign = [];
newDesign is an array. It has n number of elements accessed by integers indices.
newDesign[saveLabel] = [];
Since newDesign is a an array saveLabel should be an numerical index. The value for that index is another array.
newDesign[saveLabel]["class"] = saveClass;
newDesign[saveLabel]["style"] = [];
newDesign[saveLabel]["hover"] = [];
Here explicitly you show that you are trying to use an array as objects. Arrays do not support ['string_key']
This might very well 'work' but only because in javascript arrays are objects and there is no rule that says you can't add properties to objects at will. However all these [] are not helping you at all.
var newDesign = {label: "the label", class: saveClass};
is probably what you are looking for.

Making a subset of an array of JavaScript objects based on one of their properties?

I have a JavaScript array of objects with the same properties each, something like this:
box[0] = { name: 'somename', /* more properties... */ };
box[1] = { name: 'othername', /* more properties... */ };
box[2] = { name: 'onemorename', /* more properties... */ };
// more objects in the array...
I want to subset this array so that it only contains objects that match a "list" of names and copy the ones that don't to another array named cache maybe. I was thinking maybe I could compare this array of objects to another array which just contains a list of strings with the desired names to match against, checking each object's name property against this list to create a new array with the ones that matched. I don't know if this would work or if it is the best approach to achieve what I want, that is why I am asking for your help. Maybe checking each of 200-500 objects against a list with 100 names is not a very good thing to do, I don't know really.
Do you have any ideas on how I could do this? even better, can you point me to an example?
Thanks in advance.
Assuming the list of names you do want are stored in an array,
var wantedNames = [ "first name", "second name", .. ];
have two arrays - those matching a name and those that don't. Loop through each item in the box object, and if it contains a name from the list, then include it.
var objectsMatchingName = box.filter(function(item) {
return wantedNames.indexOf(item.name) !== -1;
});
var cache = box.filter(function(item) {
return objectsMatchingName.indexOf(item) === -1;
});
I wish there was a array difference operation of some kind, so you could do (in pseudocode):
var cache = box - objectsMatchingName

Categories

Resources