javascript objects not getting assigned correct member value - javascript

I have 2 JS arrays and I am iterating through both of them to find similar ones.
anomalies.forEach(function(anomaly) {
links.forEach(function(link) {
if ((link.source.name === anomaly.source) && (link.target.name === anomaly.target)) {
console.log("anomaly");
link.type = "anomaly";
console.log(link);
} else {
link.type = "normal";
}
});
});
console.log(links);
In a case where the value of link.type should be "anomaly", still its reflecting to be "normal".
Why is it so and what should be done?

I was an algorithmic mistake. In the provided screenshot type="normal" is the current value of the object.
Consider:
Loop1
Loop2
condition
if the condition inside loop2 is met for the link object then its type value is assigned "anomaly". But when the next iteration of loop1 occurs, and the condition is not met for the same link object, then the value is assigned "normal". Hence its an algorithmic mistake.

Looks, like each does not change start value, try that:
n = anomalies.length;
k = links.length;
for(i=0; i<n; i++){
for(j=0; j<k; j++){
if ((links[j].source.name === anomalies[i].source) && (links[j].target.name === anomalies[i].target)) {
console.log("anomaly");
links[j].type = "anomaly";
console.log(links[j]);
} else {
links[j].type = "normal";
}
}
}
console.log(links);

If you take a look at the documentation:
here
You can see that there is 3 arguments can be passed to the callback function
- element
- index
- array
If you call forEach like this:
var x=[1,2,3,4,6];
x.forEach(function(e){
if(e==3)f=9;
console.log(e);
})
console.log(x);
1
2
9
4
6
[1, 2, 3, 4, 6]
The value of the array element will not change because you are changing a buffers value.
But if you use forEach like this:
var x=[1,2,3,4,6];
x.forEach(function(e,i,a){
if(e==3)a[i]=9;
console.log(a[i]);
})
console.log(x);
1
2
9
4
6
[1, 2, 9, 4, 6]
you see that the value changed in the array.

Related

Javascript: Write a function that takes in a number, and returns an array with that number in it that many times

I'm a complete newbie to programming and mathematical concepts (took Math 101 in college) so I'm struggling with this problem:
Write a function that takes in a number, and returns an array with that number in it that many times.
Here's the code I've got so far:
function numReturn(x) {
var newArray = [];
if (typeof x === "number") {
return newArray.push[x]* x;
} else {
return null;
}
}
Here's my thought process:
Create a function that can take in a number, x.
Within that function, create a blank array so you can push values to it later.
Check if the typeof value entered in for x is a number. If it is, return it pushed to the end of the blank array. Otherwise, return null.
When I put this in the Javascript console and plug a value in, it comes back undefined. Anyone have some pointers for me?
function a(i) {
var a = new Array(i);
return a.fill(i);
}
or return new Array(i).fill(i);, for short. Test:
a(4)
// --> [4, 4, 4, 4]
Array.prototype.fill() is an ES6 method and is not yet universally implemented. Chrome and Firefox have it, IE does not - but there is a polyfill available.
Compare: http://kangax.github.io/compat-table/es6/#test-Array.prototype_methods_Array.prototype.fill
In order to do something an arbitrary number of times, one uses a loop. There are several loops, but here the for loop is most appropriate.
A for loop has the following structure:
for(var i = 0; i < x; i++) {
// ^initializer
// ^condition
// ^increment
//body
}
The initializer is the first thing that is done when entering the loop. IN this case, it means a variable named i is set to 0. Then the condition x is checked. If the condition i < x holds, the loop is executed: the body is executed. After the body is executed, the increment is performed (here i++), and then the condition is rechecked, if the condition still holds, the loop is executed again, and so on.
You can apply this concept as follows:
function numReturn(x) {
var newArray = [];
if (typeof x === "number") {
for(var i = 0; i < x; i++) {
newArray.push(x);
}
return newArray;
} else {
return null;
}
}
This: newArray.push[x]* x does not push x times. The * operator just multiplies numbers, always and only. You want to push x times, so use a for like this:
for (var i = 0; i < x; i++ )
newArray.push(x);
and then return newArray.
Taking from answer of Most efficient way to create a zero filled JavaScript array?
function numReturn(x){
return Array.apply(null, Array(x)).map(Number.prototype.valueOf,x);
}
console.log(numReturn(10)); // [10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
var n = 7
var result = Array.apply(null, {length: n}).map(function(){return n})
// Demo output
document.write(JSON.stringify(result))
As function:
function numReturn(x) {
if (typeof x === "number") {
return Array.apply(null, {length: n}).map(function(){return n})
} else {
return null;
}
}

Using 'in' keyword to check for 0 always returns true?

Take the following piece of code:
var testArr = [1, 2, 3, 4, 5];
function check(num) {
if (num !== undefined) {
if (num in testArr) {
alert("in");
} else {
alert("not in");
}
}
}
With the check() function I try to check whether a given parameter is part of the testArr array or not.
In general the function works fine, only when checking for 0 the condition is met, although 0 is not part of the array. See for yourself: Fiddle
Why is this happening?
One possible solution I could think of is that 0 is evaluated as false in some cases (== vs ===), but when passing false as argument, the condition is not met, which does not make any sense to me – I am puzzled.
In this case you returned that the index exists in the array but not the value. See this documentation in operator. I think that you must validate values of array with indexOf function.
You want to use the [].indexOf(elem) (doc) and check for -1 if it's not in the array. There's also a few other ways mentioned in this question How do I check if an array includes an object in JavaScript?
Your code would be updated as follows:
var testArr = [1, 2, 3, 4, 5];
function check(num) {
if (num !== undefined) {
if (testArr.indexOf(num) != -1) {
alert("in");
} else {
alert("not in");
}
}
}
The in operator searches for keys and 0 will be a valid index in any nonempty array. in does not return true for all arrays. Try it with an empty array []
"in" is checking by key.
You have testArr[0] so you can get alert("in").
That is, if u use check(0)~check(4) will be alert("in"),
other will be alert("not in") such as check(5).
var testArr = [1, 2, 3, 4, 5];
function check(num) {
if (num in testArr) {
return "check(" + i + ") = in ";
} else {
return "check(" + i + ") = not in ";
}
}
for (var i = 0; i <= 6; i++) {
document.write(check(i) + "<br>")
}
The prop parameter from the in operator will search a property or check if an index exists.
From the documentation:
prop: A string or numeric expression representing a property name or
array index.
And from one of it's examples:
You must specify the index number, not the value at that index.
If you do:
<script>
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
'length' in trees // returns true because length is a property.
</script>
So in your case you are asking the check function if index 0 exists.

Javascript: add value to array while looping that will then also be included in the loop

Sorry if this is a dupplicate, can't seem to find it.
var a = [1,2,3,4];
a.forEach(function(value){
if(value == 1) a.push(5);
console.log(value);
});
I wonder if there is a way (any sort of loop or datatype) so that this will ouput 1 2 3 4 5 during the loop (or in any order, as long as all the 5 numbers are in there)
Using Array.prototype.forEach() will not apply the callback to elements that are appended to, or removed from, the array during execution. From the specification:
The range of elements processed by forEach is set before the first
call to callbackfn. Elements which are appended to the array after the
call to forEach begins will not be visited by callbackfn.
You can, however, use a standard for loop with the conditional checking the current length of the array during each iteration:
for (var i = 0; i < a.length; i++) {
if (a[i] == 1) a.push(5);
console.log(a[i]);
}
Obvious solution :
var a = [1,2,3,4];
for (var i=0; i<a.length; i++){
var value = a[i];
if(value == 1) a.push(5);
console.log(value);
}
Since you appear to use Harmony, how about a generator like this:
function *iter(array) {
for (var n = 0; n < array.length; n++)
yield array[n];
}
and then
var a = [1,2,3,4];
for(var p of iter(a)) {
if(p == 1) a.push(5)
console.log(p)
}
prints 1 2 3 4 5
If you need a method that uses a callback as apposed to the for loop reduce will work.
var a = [1,2,3,4];
var result = a.reduce(function(total, item) {
total.push(item);
if (item === 4) total.push(5);
return total;
}, []);
console.log(result);
Better Alternate solution:
if (a.indexOf(1) >= 0) a.push(5);
a.forEach( ... );
OK, maybe not strictly better, since it traverses the array twice. However you ought to consider why you're trying to modify the array whilst iterating over it in the first place. It's an unusual situation.
SO this is a quick test that seems to work well :
var a = [1,2,3,4,5];
a.forEach (function (val,index,array) {
if (val == 5) {
array.push (6);
};
console.log (val);
});
a.forEach(function fn(item, index) {
if (item == 5) {
array.push (6);
};
})
var a = [1,2,3,4];
Object.keys(a).forEach(idx => {
if(a[idx]==1) a.push(5);
console.log(a[idx]);
});
OP here. I've since learned that ES6 Sets do include items added during forEach.
So if you can use a set instead of an array, you can do:
var a = new Set([1,2,3,4]);
a.forEach(function(value){
if(value == 1) a.add(5);
console.log(value);
});
which does indeed log 5 as well.
Just an alternative to the for loop. Of course Sets are different than arrays in several ways, so you'd need to understand the differences and how it effects your other code.

need clarification on this code I am writing to find the mode of an array

For some reason I have just not been able to understand what is going on in this code
function mode(arr){
var modecount = {}; // creating an object to add number and its mode
for(var i = 0; i < arr.length; i++){ //iterating through array
if(!modecount[arr[i]]){ /*This part I don't understand what do these two lines mean?
I interpret it as if the current number in the array doesn't equal a number already
in the modecount object then it equals 0 */
modecount[arr[i]] = 0;
}
modecount[arr[i]] += 1; /* also what is happening here it is adding 1 to the value
of modecount but why does it not add 1 to unique numbers and how does the code know
to add 1 if it finds duplicates? */
}
return modecount;
}
mode([3,4,3,43,4,34,34,3,3,3,3,3]);
It seems like Ive been staring at this code for several hours and just cant get it. Somebody please explain this to me like I am a 3 year old.
Here's the high level explanation:
It's taking a list of numbers, and it's counting the number of times each number appears in that list.
Now, here are the inline explanations:
function mode(arr){
// Initialize an object literal
var modecount = {};
for(var i = 0; i < arr.length; i++){
// If the value of arr[i] does NOT exist in the object modecount
if (!modecount[arr[i]]) {
// Set the count of arr[i] to zero
// Why? Because it if doesn't exist
// then doing modecount[arr[i]] += 1 will throw an error
// because modecount[arr[i]] will be undefined.
modecount[arr[i]] = 0;
}
// We increase the count of arr[i] in modecount by 1.
// You asked about duplicates.
// It handles duplicates fine because modecount
// acts as a hash map (every key is unique).
// Doing modecount[5] over and over will
// give you the same value associated with 5.
modecount[arr[i]] += 1;
}
return modecount;
}
// Call the function with our array
mode([3,4,3,43,4,34,34,3,3,3,3,3]);
I think this logic, while correct, can be improved. The assignment to 0 that follows the first IF statement reduces clarity. Why set to zero if it doesn't exist? It only makes sense after I read the next few lines.
Here's how I would rewrite it:
function mode(arr) {
var modeCount = {};
for (var i = 0; i < arr.length; i++) {
// Save the value so we don't have to do arr[i] every time
var currMode = arr[i];
// If it exists
if (modeCount[currMode]) {
// Increment by 1
modeCount[currMode]++;
} else {
// Otherwise, it's the first one
modeCount[currMode] = 1;
}
}
return modeCount;
}
console.log(mode([3, 4, 3, 43, 4, 34, 34, 3, 3, 3, 3, 3]))
It is basically counting the number of time a particular value in the passed array exists but with base value of 0 for first occurence of the value to initialize the property at that value.
Even though modecount is specified as an object, the way one can access properties of an object in a variable manner is by using bracket notation. So the output of
mode([3,4,3,43,4,34,34,3,3,3,3,3]);
Would be:
{ 3: 7, 4: 2, 43: 1, 34: 2 }
I hope this helps. I reworded a couple variables because i felt it read a bit nicer.
function mode(arr){
// create an index for our counter
var index = {};
// a normal for-loop to iterate through the passed in numbers
for(var i=0, num; i<arr.length; i++){
// each time the foor loop runs, set num to arr[i]
num = arr[i];
// if no valid counter was found...
if(!index[num]){
// then create a new counter; initialize to 0
index[num] = 0;
}
// add 1 to the counter
index[num] += 1;
}
// return the counters
return index;
}
mode([3,4,3,43,4,34,34,3,3,3,3,3]);
I'd assume the first part is just shorthand to check if modecount[arr[i]] has been initialized/defined yet. If it returns a "falsey" value it is either not initialized (accessing modecount[arr[i]] returns undefined) or has a 0 value - the latter is not possible because the next line always immediately increments the 0 to 1.
Note you could replace this check with if(typeof(modecount[arr[i]]) === "undefined") for equivalent and more explicit behavior.
As for the overall operation of the function, consider the following pesudocode:
var modecount = {}
foreach element in array:
if modecount[element.value] is not defined:
modecount[element.value] = 0
modecount[element.value]++
The function loops through the passed array, storing each incident number as a number:count pair on the modecount object. So as your function works, the modecount object is going to look like this:
{}
{ 3: 1 }
{ 3: 1, 4: 1 }
{ 3: 2, 4: 1 }
{ 3: 2, 4: 1, 43: 1 }
{ 3: 2, 4: 2, 43: 1 }
and so on...

Javascript - Do something when an element in two arrays are the same?

I found a solution to where I get returned an array of elements without duplicates:
Array1 = Array1.filter(function(val) {
return Array2.indexOf(val) == -1;
});
However, I want to modify this code just a little bit. Instead of being returned an array without duplicates, I want to do something when there is a duplicate. The problem is, I'm not sure how exactly this code works. The thing is I'm not sure how val gets set, or what it even is.
for (var i = 0; i < json.length; i++) {
var item = json[i];
// if json.indexOf(val?), do something
}
Read the docs for the Array filter method then. The val parameter of the callback will be passed the single array items, i.e. json[i] or item in your case:
for (var i = 0; i < json.length; i++) {
var item = json[i];
if (json.indexOf(item) >= 0) {
// do something
}
}
var newArray = array1.filter(function(v, i) {
return array1.indexOf(v) == i;
});
This will return only unique itesm from array1;
array1.filter(function(v, i) {
// write your code here ('v' is individual value and 'i' is its index)
// don't return any anything if you don't want unique array to be returned.
// 'array1.indexOf(v) == i' checks if current value is duplicate from previous any values.
// try putting console.log on values you don't understand like (console.log(v,i) for values of 'v' and 'i')
return array1.indexOf(v) == i;
});
and off-curse you can loop an array with for loop as
for(i in array1){
// where i is index of array1, to get current value use array1[i]
if(array2.indexOf(array1[i]) >= 0){
// do something
}
console.log(i);
}
val is set by Array.prototype.filter, which calls the callback function on each element in the array. Since you don't want to filter you can use Array.prototype.forEach instead, which also calls the callback function once for each element in the array:
Array1.forEach(
// This function is called once per element in Array1
function(val){
if(Array2.indexOf(val) != -1){ // Check if that element is also in Array2
// `val` is in both arrays,
// Do something with it
}
}
);
You can utilize some modern libraries... like underscorejs.
Intersection is what you're looking for i guess: http://underscorejs.org/#intersection
_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2]
So your code may be something like
if(_.insersection(arr1, arr2)){
//since [] array is Falsy in JS this will work as a charm
}
From MDN: indexOf
Returns the first index at which a given element can be found in the array, or -1 if it is not present.
From MDN: filter
Creates a new array with all elements that pass the test implemented by the provided function.
The first function works by returning true when an item from array1 isn't found in array2 (== -1). i.e.: Iterate through A and add anything not found in B.
So, to change to return only duplicates return true for anything that is found in both:
Array1 = Array1.filter(function(val) {
return Array2.indexOf(val) >= 0;
});
Array1 now contains only items with duplicates.

Categories