find item in array with object properties - javascript

I'm trying to check if something exists in an array.
here is where I make the object...
function makeEventObject(eventName, idzName, classzName) {
function eventDetails(eventName, idzName, classzName) {
this.eventName = eventName;
this.idzName = idzName;
this.classzName = classzName;
}
let eventObject = new eventDetails(eventName, idzName, classzName);
console.log(Object.getOwnPropertyNames(eventObject));
console.log(eventObject.idzName);
// console.log(eventObject);
return eventObject;
}
I can access the eventObject.keys or eventObject.properties >> console.log
The thing I can't figure out, is, I want to push it to an array. But with conditions. If its already in the array, then don't add. But the conditions are also based on on other eventObject.properties. for example: the 1st check is to see if it exists in the array. Because the array is empty initially it should return = undefined, SO add the 1st item. But when the second item comes through, if the eventObject.idZName && the eventObject.classzName is the same as the 2nd do NOT add. if, the .idZname is different, and the .classZname is the same, replace the array element with same .classZname. if the both the .classZname and .idZname are different from what's in the array or undefined. ADD.
its a series of filters, that I came to see to get functional. below are the push to array functions and checker functions. I tried to put both into the same function, but i kept getting .push() errors.
function makeEventList(eventObject) {
eventList.push(eventObject);
console.log(eventList);
let a = eventList.length;
console.log(a);
}
function eventChecker(eList, eventObject){
var exists = eList.find(function(eventObject){return eventObject.eventName === eList[eventObject.eventName];});
console.log(exists);
}
Any Ideas...and what I'm doing wrong? so far tried IF statements, .includes(), .filter(), .each().
currently I'm getting cannot read property of 'find;..
a live copy is available at fiddle -> https://jsfiddle.net/j1xtvmLy/461/

Based on your jsfiddle eList is undefined because you didn't pass in arguments into eventChecker call.
Make sure that when you're relying on parameters that you pass in arguments in the function call.
Also your let eList = makeEventList(eventObject); assumes that it'll return an array but you haven't created or returned the array in your function makeEventList

Related

jQuery's .add on an empty set?

I am working on a plugin with quite a few options and as a consequence I am trying to keep track of a set of elements and put them in a variable. The variable cannot be empty (but that is of no concern here). Let's say there are only two options, then the variable will hold one or two elements as a jQuery object, i.e. $("#el1, #el2"). I tried the following, but the result of adding is still $([]).
var track = $([]);
someFunc() {
if (option1) track.add("#el1");
if (option2) track.add("#el2");
}
// result is `$([])`
Note that I don't want an array back, but a jQuery selector as I posted in the example above.
You could first sort out which elements/selectors you need.
And then use these to init the track variable with an jQuery object passing in all the relevant selectors.
var track = someFunc();
// you would have to check the length of `track` first as it may be only an empty array (length == 0) and no real jQuery object
if (track.length) {
//...
}
// returns a jQuery object with all the matched elements
// or an empty array if there is no relevant selector
function someFunc() {
// place to store the selectors
var selectors = [];
// store the relevant selectors in <selectors>
if (option1) selectors.push("#el1");
if (option2) selectors.push("#el2");
// if there is at least one selector in <selectors>
if (selectors.length > 0) {
// create a jQuery object of them and return it
return $(selectors.join())
} else {
// otherwise we return an empty array
// this allows us to use .length in both cases
return [];
}
// or always return a jQuery object
// return $(selectors.join());
}
Use a array join on coma:
var elements = [];
elements.push('#one');
console.log(elements.join(','));
$(elements.join(','));
https://jsfiddle.net/8xx8x1xe/

array undefined after pushing to object

I'm pushing an object into an array of objects. One of the properties of the object (which is an array) is showing up as undefined, after the object is pushed to the array. If you look at my code below, where it says, "WHY IS THIS SHOWING IN CONSOLE?" - it doesn't make sense because if the array is undefined, it should have been undefined in both of the previous two checks (where it says "THIS IS NOT SHOWING IN CONSOLE."). This is driving me crazy. SOS. Please help.
var pathCopy = unit.path; // THIS IS AN ARRAY AND IT IS NOT EMPY
var directionCopy = unit.direction;
if (pathCopy.length < 1) {
console.log('THIS IS NOT SHOWING IN CONSOLE');
}
var object = {
'type': 'move',
'time': gameTime,
'name': unit.name,
'vector': pathCopy,
'direction': directionCopy
};
currentGameEvents.push(object);
if (object.vector.length < 1) {
console.log('THIS IS NOT SHOWING IN CONSOLE');
}
for (var i = 0; i < currentGameEvents.length; i++) {
if (currentGameEvents[i].vector.length < 1) {
console.log('WHY IS THIS SHOWING IN CONSOLE??');
}
}
I’m not sure how or why, but your example works, if I insert the undefined variables (i.e. I replaced unit.path with [345,34623,52] or something that is an array literal).
The only difference to that is, that you actually assign the reference to that array, instead of declaring a new array.
var pathCopy = unit.path; // pathCopy and unit.path are the SAME array
var pathCopy = [345,346,345]; // pathCopy is a completely NEW array
To fix this, try something like
var pathCopy = unit.path.slice(); // pathCopy is a completely NEW array that contains the same values as unit.path
whenever you want to copy an array; add .slice() at the end!
Again, this is deducing from the only difference between your code and what I tried, and this is probably the reason, why your code doesn’t work.
Another assumption is that currentGameEvents is an Array. Your code wouldn’t work at all, otherwise. I’m mentioning this because the title states that you were trying to push to an object, which isn’t possible.

How do I add elements to a dynamic array and exclude exsisting elements

function addNumifnotThere(numer){
var numCent = [];
numCent.forEach(function(){
if(numer in numCent)
console.log("you logged that");
else
numCent.push(numer);
});
return numCent;
}
This is my current code, what its attempting to do is read an array and if there is already an element exits the loop and says "you already logged that", obviously if it cannot find a similar element then it pushes it to the array.
I want this to work dynamically so we cannot know the size of the array beforehand, so the first element passed as an argument should be put into the array, (addNum(1) should have the array print out [1], calling addNum(1) again should print "you already logged that")
However there are two problems with this
1) Trying to push to a new array without any entries means everything is undefined and therefore trying to traverse the array just causes the program to print [].
2) Adding some random elements to the array just to make it work, in this case numCent=[1,2,3] has other issues, mainly that adding a number above 3 causes the code to print incorrect information. In this case addNum(5) should print [1,2,3,5] but instead prints [1,2,3,5,5,5]
I know this has to be a simple mistake but I've been dragging myself too long to not ask for help.
EDIT: Thanks to the many outstanding answers here I have now leanred about the indexOf method, thank you guys so much.
For every non-match you are pushing the number. Use something like this
var numCent = [];
function addNumifnotThere(numer)
{
var index = numCent.indexOf(number);
if(index >=0)
{
console.log("you logged that");
}
else
{
numCent.push(number);
}
return numCent;
}
Use Array.prototype.indexOf
var numCent = [];
function addNum(numer){
if (numCent.indexOf(numer) > -1)
{
console.log("Number already in array");
}
else
{
numCent.push(numer);
}
}
//DEMO CODE, not part of solution
document.querySelector("button").addEventListener("click", function(){
if (document.querySelector("input").value.length > 0)
{
addNum(document.querySelector("input").value);
document.querySelector("div").innerHTML = numCent.join(", ");
}
}, false);
Output
<div id="output"></div>
<input />
<button>Add number</button>
indexOf tests if an element is inside the array and returns its index. If not found it will return -1. You can test for this. You can try it for your self in this snippet. It will only allow you to add a number (or any string, in this example) once.
I also was confused by the newCent array declaration inside the function. I think, based upon the content of your question, you meant this.
If you want the array held in the instance, you can do it like this.
function AddIf(arr){
if( arr || !this.arr ) {
this.arr = arr || [];
}
return function(number) {
if( this.arr.indexOf(number) >= 0 ) {
console.log("Already Present!");
} else {
this.arr.push(number);
}
return this.arr;
}.bind(this);
}
// Usage would be like this:
// var addIf = new AddIf([1, 2, 3]);
// addIf(10); // returns [1, 2, 3, 10]
// addIf(10); // logs "Already Present!", doesn't add 10 to array
This basically returns a function, with this bound to the function being called. If you pass in an initial array, it will use that array to compare to when adding it to the array.
You can catch the return function and call it as you would want to. If you don't call new when invoking however, it will share the same array instance (and have a funky way of being called, AddIf()(10)).
I used fn.bind() to ensure the function gets called in the correct context every time, if you were wondering why I called it like that.
Do do this cleanly, I'd consider prototyping the global Array object and adding a method to push values but only if they're unique to the array. Something like this:
Array.prototype.pushUnique = function (item) {
if (this.indexOf(item) != -1) {
console.log("Item with value of " + item + " already exists in the array."
}
else {
this.push(item);
}
}
If you're not comfortable prototypeing global types like Array, you can build the same thing in a procedural pattern:
function arrayPushUnique (arr, item) {
if (arr.indexOf(item) != -1) {
console.log("Item with value of " + item + " already exists in the array."
}
else {
arr.push(item);
}
}
Then to use it, simply create a new empty array and start pushing things to it.
var numCent = [];
// The Array.prototype method
numCent.pushUnique(number);
// The procedural method
arrayPushUnique(numCent, number);

Passing array of objects to a js function

i am trying for the first time to implement OOP in javascript and i got stuck on a recursive function when i try to send an array of objects to this function. So, i have the "Pitic" class (pitic means midget in romanian) with some propreties:
function Pitic(piticID) {
this.id = piticID;
this.inaltime = null;
this.greutate = null;
this.genereazaGreutate();
this.genereazaInaltime();
}
I'm now generating some midgets and storing them in the public piticiCollection Array variable. The "genereazaGreutate" and "genereazaInaltime" are function to generate random values for the inaltime and greutate values.
var pitic = new Pitic(idPitic);
piticiCollection.push(pitic);
The problem appears when i try to send the array of midgets to a function because all i get is only the first item of the array.
So, before i call the function, i have piticiCollection array with 4 objects:
midgets are safe and sound http://img443.imageshack.us/img443/484/yr4f.png
And as soon as i call the function with the piticiCollection as a parameter i loose 3 midgets! :(
most of the midgets are gone http://img201.imageshack.us/img201/5808/7od5.png
p.s. please excuse me for my bad english..
[EDIT]
Here is a fiddle of my full code: http://jsfiddle.net/WT7Ud/ I call the function on line 56 and as soon as the debugger hits line 60 i loose array items.
I have solved my problem by creating a copy of the array before using it in the function. Strange :(
function determinaPerechi(somePitici) {
var piticDeComparat, colectieDePiticiCopy;
colectieDePiticiCopy = somePitici;
for (var i = 1; i < colectieDePiticiCopy.length; i++) {
var piticDeComparat2 = null;
piticDeComparat = colectieDePiticiCopy[0];
piticDeComparat2 = colectieDePiticiCopy[i];
if (piticDeComparat.inaltime < piticDeComparat2.inaltime) {
//Perechea poate fi prietena
}
}
//colectieDePiticiCopy.splice(0, 1);
if (colectieDePiticiCopy.length == 0) {
//alert("finish");
return;
}
determinaPerechi(colectieDePiticiCopy);
//test(ttt);
}
Your determinaPerechiPosibile is modifying the original array on this line:
colectieDePitici.splice(1, colectieDePitici.length);
In particular, it is removing all but the first element. You probably should be using slice to non-destructively extract the part of the array you want to recurse on.
As Ted Hopp mentioned, the problem appears to be the line
colectieDePitici.splice(1, colectieDePitici.length);
in combination with this line:
determinaPerechiPosibile(colectieDePiticiCopy);
If those two lines are commented out, the array maintains its original length.

Can I loop through 2 objects at the same time in JavaScript?

related (sort of) to this question. I have written a script that will loop through an object to search for a certain string in the referring URL. The object is as follows:
var searchProviders = {
"google": "google.com",
"bing": "bing.com",
"msn": "search.msn",
"yahoo": "yahoo.co",
"mywebsearch": "mywebsearch.com",
"aol": "search.aol.co",
"baidu": "baidu.co",
"yandex": "yandex.com"
};
The for..in loop I have used to loop through this is:
for (var mc_u20 in mc_searchProviders && mc_socialNetworks) {
if(!mc_searchProviders.hasOwnProperty(mc_u20)) {continue;}
var mc_URL = mc_searchProviders[mc_u20];
if (mc_refURL.search(mc_URL) != -1) {
mc_trackerReport(mc_u20);
return false;
}
Now I have another object let's call it socialNetworks which has the following construct:
var socialNetworks = {"facebook" : "facebook.co" }
My question is, can I loop through both of these objects using just one function? the reason I ask is the variable mc_u20 you can see is passed back to the mc_trackerReport function and what I need is for the mc_u20 to either pass back a value from the searchProviders object or from the socialNetworks object. Is there a way that I can do this?
EDIT: Apologies as this wasn't explained properly. What I am trying to do is, search the referring URL for a string contained within either of the 2 objects. So for example I'm doing something like:
var mc_refURL = document.referrer +'';
And then searching mc_refURL for one of the keys in the object, e.g. "google.com", "bing.com" etc. 9this currently works (for just one object). The resulting key is then passed to another function. What I need to do is search through the second object too and return that value. Am I just overcomplicating things?
If I understand your question correctly, you have a variable mc_refURL which contains some URL. You want to search through both searchProviders and socialNetworks to see if that URL exists as a value in either object, and if it does you want to call the mc_trackerReport() function with the property name that goes with that URL.
E.g., for mc_refURL === "yahoo.co" you want to call mc_trackerReport("yahoo"), and for mc_ref_URL === "facebook.co" you want to call mc_trackerReport("facebook").
You don't say what to do if the same URL appears in both objects, so I'll assume you want to use whichever is found first.
I wouldn't create a single merged object with all the properties, because that would lose information if the same property name appeared in both original objects with a different URL in each object such as in an example like a searchProvider item "google" : "google.co" and a socialNetworks item "google" : "plus.google.com".
Instead I'd suggest making an array that contains both objects. Loop through that array and at each iteration run your original loop. Something like this:
var urlLists = [
mc_searchProviders,
mc_socialNetworks
],
i,
mc_u20;
for (i = 0; i < urlLists.length; i++) {
for (mc_u20 in urlLists[i]) {
if(!urlLists[i].hasOwnProperty(mc_u20))
continue;
if (mc_refURL.search(urlLists[i][mc_u20]) != -1) {
mc_trackerReport(mc_u20);
return false;
}
}
}
The array of objects approach is efficient, with no copying properties around or anything, and also if you later add another list of URLs, say programmingForums or something you simply add that to the end of the array.
You could combine the two objects into one before your loop. There's several approaches here:
How can I merge properties of two JavaScript objects dynamically?
var everything = searchProviders;
for (var attrname in socialNetworks) { everything[attrname] = socialNetworks[attrname]; }
for(var mc_u20 in everything) {
// ...
}
for (var i = 0; i < mc_searchProviders.length; i++) {
var searchProvider = mc_searchProviders[i];
var socialNetwork = mc_socialNetworks[i];
if (socialNetwork != undefined) {
// Code.
}
}
Or am i horribly misunderstanding something?

Categories