difference between push and normal array assignment in javascript - javascript

I'm using flot api to draw charts. Look at this chart type HERE.
In that example they've used values like,
var sin = [], cos = [];
for (var i = 0; i < 14; i += 0.5) {
sin.push([i, Math.sin(i)]);
cos.push([i, Math.cos(i)]);
}
Now the chart was drawn "curved" lines, when i replaced the
sin.push([i, Math.sin(i)]);
cos.push([i, Math.cos(i)]);
with,
sin[i]=[i, Math.sin(i)];
cos[i]=[i, Math.cos(i)];
Then the chart gets drawn using straight lines. I've two questions now.
1) What is the difference between the two types of array assignments?
2) Is this because of difference in array assignments or the API behaviour?
any help greatly appreciated! Thanks.
Edit: Set i to increment by 1 and set different values using push method or default assignment, you'll get the same result.

The i is not Integer. You can use only int in array index.
1) What is the difference between the two types of array assignments?
A) None, except the push places next int for index.
2) Is this because of difference in array assignments or the API behaviour?
A) Yes with your way the array is invalid, because the 1.5 value for a key is parsed as a string and api can not read the array as it expect.
Try using apis way or using different values for for statement.

I think there's a problem with i increment. It is clear that on every iteration i is increased by 0.5, not 1. Look:
for (var i = 0; i < 14; i += 0.5)
So sin[i]=... won't work properly. But sin.push(...) will work.

Array indexes can't be fractions and are always strings, so the number 1.5 is being converted to a string '1.5' and the sequence will be '0', '0.5', '1', '1.5' and so on. But using push, all indexes will be integer strings, so will be 0, 1, 2, etc.
No doubt an integer based loop is being used to read the values from the array, so it is skipping the .5 ones (i.e. every second element) and giving jagged edges.

Generally this would work, but in this case you're incrementing i by 0.5 which results in i being a float-value.
Look at the output of both variants:
// push
// cos
[[0, 1],
[0.5, 0.8775825618903728],
[1, 0.5403023058681398],
[1.5, 0.0707372016677029],
[2, -0.4161468365471424],
[2.5, -0.8011436155469337], ...]
// sin
[[0, 0],
[0.5, 0.479425538604203],
[1, 0.8414709848078965],
[1.5, 0.9974949866040544],
[2, 0.9092974268256817],
[2.5, 0.5984721441039564], ...]
// array-index
// cos
[[0, 1],
[1, 0.5403023058681398],
[2, -0.4161468365471424],
[3, -0.9899924966004454],
[4, -0.6536436208636119], ...]
// sin
[[0, 0],
[1, 0.8414709848078965],
[2, 0.9092974268256817],
[3, 0.1411200080598672],
[4, -0.7568024953079282], ...]

Related

Problem with getting javascript to forget a variables value

I'm trying to solve a coding challenge
it gives me an array and waits for the answer ,then gives me the next array and so on.
https://www.codewars.com/kata/5648b12ce68d9daa6b000099/train/javascript
I am trying to take this input: var busStops = [[10,0],[3,5],[5,8]] and return 5.
the code is supposed to add the first in each pair to a total while subtracting the second in each pair from the total eg: 10 - 0 + 3 - 5 + 5 - 8 = 5
First my code loops through the inner arrays and outer array ,pushing it into myarr as a regular array eg: [10,0,3,5,5,8].
It then adds the value if it is index is 0 or even and subtracts it if the index is odd.
This actually works!
Until it is given a second array eg: [[3,0],[9,1],[4,10],[12,2],[6,1],[7,10]]
It is still calculating the total correctly but is still remembering the total from the first array meaning it is returning 22 instead of 17
Why?
There is a var answer = 0 that is being executed ahead of the second loop
It should forget the value of the previous answer.
Right?
Edit: I figured out my problem. I just needed to empty myarr after the total was calculated!
let myarr = [];
var number = function (busStops) {
for (var i = 0; i < busStops.length; i++) {
for (var j = 0; j < busStops[i].length; j++) {
/*console.log(busStops[i][j]);*/
myarr.push(busStops[i][j]);
}
}
console.log("test");
var answer = 0;
console.log("test again");
for (let t = 0; t < myarr.length; t++) {
if (t == 0 || t % 2 == 0) {
answer = answer + myarr[t];
} else {
answer = answer - myarr[t];
}
}
console.log(answer);
return answer;
};
The task at your hand tries to somehow find a value (an integer) from an array of arrays (multidimensional array). That task seems to be reducing that multidimensional array into a single integer.
Luckily, JavaScript has some powerful array methods and one of them is the reduce method:
The reduce() method executes a user-supplied "reducer" callback function on each element of the array, in order, passing in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is a single value. Source: MDN
The reduce method tries to reduce an array's elements into a single value and in your case we want to reduce that multidimensional array into a single value that is the number persons who are still in the bus.
Before typing some code, let's dig a bit deeper into the reduce method:
It accepts 2 parameters, a callback function that acts as the reducer and the initial value to be used in the first iteration of the reduce method.
The reducer callback function, on its own, accepts 4 parameters that are supplied by the reduce method. You may learn more about those parameters here as am only going to focus on the first 2 parameters the reducer accepts:
previousValue: hold the value from the previous reducer call. On first call, it contains the value you set to the initial value parameter of the reduce method or, if you didn't supply an initial value, previousValue shall hold the value of your array's first element (arr[0]).
currentValue: hold the current reduce iteration's item.
Now, let's get back to the task we have, we need to calculate the number of persons who are still in the bus based on a supplied multidimensional array. Each item in that multidimensional array is an array of two values where the result we need at the end is: the sum of the differences between each array, in the multidimensional array, first and second values (sum = multiDim[i][0] - multiDim[i][1] + multiDim[i + 1][0] + multiDim[i + 1][1] etc...).
To solve this task, we'll reduce that multidimensional array into a single number (let's call it result) by using a simple reducer function that will start by an initial value of 0 (as we're calculating a sum in our case) and will add, to the result, the difference between the first and the second values of the array supplied by the reduce at each iteration.
To illustrate, here's a live demo:
/**
* a function that calculates and returns the number of person who are still in the bus or precisely, the sum of the differences between "c[0]" and "c[1]"
* busArray: the supplied multidimensional array to reduce
* the reducer accepts two parameters:
* r: the result from the last call to the reducer function (initially set to 0, the initial value (see second parameter passed to the "reduce" method))
c: hold the current iteration's array.
*/
const calculateWhoAreInTheBus = busArray => busArray.reduce((r, c) => r += c[0] - c[1], 0);
/** test the created "calculateWhoAreInTheBus" function */
console.log(calculateWhoAreInTheBus([
[10, 0],
[3, 5],
[5, 8]
])); // should print: 5
console.log(calculateWhoAreInTheBus([
[3, 0],
[9, 1],
[4, 10],
[12, 2],
[6, 1],
[7, 10]
])); // should print: 17
console.log(calculateWhoAreInTheBus([
[3, 0],
[9, 1],
[4, 8],
[12, 2],
[6, 1],
[7, 8]
])); // should print: 21
console.log(calculateWhoAreInTheBus([
[0, 0],
[0, 0]
])); // should print: 0
I would advice you to use Array.prototype.reduce instead. For example like this:
const reducer = (previous, current) => previous + current[0] - current[1];
const answer = busStops.reduce(reducer, 0);
It is very brief (although this is not a goal in and of itself) and the reducer function does almost trivial work, so it does not complicate unneccesarily. Best of all it encapsulates the functionality with a minimal need of extra variables.
Othwerwise you could simplify your function a bit but use the let keyword to keep variables locked to scope like:
function number(busStops) {
let answer = 0;
for (let bs of busStops) {
answer += bs[0] - bs[1];
}
return answer;
}

How to add column names to 2d array when printing with console.table() javascript

If I have a 2d array like this...
var x = [
[0, 1, 2],
[0, 1, 2],
[0, 1, 2]
]
And I want to print it to the console using console.table() but I also want to add column names, how do I do that?
I see in the documentation its really easy when its an array of objects, but when I try to add column names to this 2d array it messes with the array dimensions and does not print correctly.
EDIT:
All of the answers this far have said what I said I already knew, that this was easy to do with an array of objects. My question is, "Is it possible to add column names if you are passing a 2d array."
I tried to console.table with your 2d array compare with array of object, Hope this is what you looking for.
You need to pass an array of objects to console.table() in order for it to display with column names, exammple below using your data:
const arrayOfObjects = new Array(10).fill({
columnOne : 0,
columnTwo: 1,
columnThree: 2
})
console.table(arrayOfObjects)
Here is a screenshot directly from the Developer Tools Console in Chrome.
More info can be found here regarding this function: https://developer.mozilla.org/en-US/docs/Web/API/Console/table
If the array contains objects, then the columns are labeled with the property name.
So you can convert the elements to objects with relevant names as properties.
var x = [
[0, 1, 2],
[0, 1, 2],
[0, 1, 2]
]
function ARR(first, second, third) {
this.first = first;
this.second = second;
this.third = third;
}
let itemArr = x.map( item => new ARR(...item))
console.table(itemArr);

Generating an array of arrays that when added equals a given number

i'm working on a bigger problem but am a little stuck on a certain issue. Hopefully, I can explain it clearly! I am looking to generate an array of arrays where each individual array has elements then when added together equal a certain number. An example would be:
target = 4
solution : [[1,1,1,1], [1,1,2], [2,2], [1,3], [4]]
edit: to make the question more clear, the solution should contain every possible combination of positive integers that will equal the target
You could take a recursive approach and loop from the last found item or one and call the function until no more values are to disperse.
function x(count) {
function iter(left, right) {
if (!left) return result.push(right);
for (var i = right[right.length - 1] || 1; i <= left; i++)
iter(left - i, [...right, i]);
}
var result = []
iter(count, []);
return result;
}
x(4).map(a => console.log(...a));
I'm not sure what language you were working in. Also, it's general StackOverflow etiquette to show what you have already tried an what exact step you got stuck on. That said, here is some Python code that does what you want.
This problem is easy to solve as a recursive function. If you have some number n, the first number in a list of sums of n could be any number between 1 and n. Call that number i. Once it's picked, the rest of the list should sum to n - i. So just make a recursive function that adds up the results for all i's that are less than n and all the results for each of the solutions to n-i.
def get_sum_components(n):
# ignore negatives
if n <= 0:
raise ValueError("n must be a positive int")
# The only way to sum to 1 is [1]. This is the base case
if n == 1:
return [[1]]
results = []
# imagine that the first number in the list of sum components was i
for i in range(1, n):
remainder = n - i
# get_sum_components(remainder) will return a list of solutions for n-i
for result in get_sum_components(remainder):
# don't forget to add i back to the beginning so they sum to n
result = [i] + result
results.append(result)
# lastly, just the number itself is always an answer
results.append([n])
return results
print(get_sum_components(4))
# gives [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]]
If you don't care about order, this will create some duplicates (like [1, 3], [3, 1]). It should be easy to filter those out, though. (Just sort all the lists and then use a dict/set to remove duplicates)

Javascript: How to initialize a 2 dimensional array

I thought initializing an multi dimensional array would be easy:
row = Array(4).fill(0)
block = Array(4).fill(row)
block[2][2] = 15
but that just creates an array of one row, 4 times, so if I assign block[2][2] = 15, then the whole column is 15.
(4) [Array(4), Array(4), Array(4), Array(4)]
0:(4) [0, 0, 15, 0]
1:(4) [0, 0, 15, 0]
2:(4) [0, 0, 15, 0]
3:(4) [0, 0, 15, 0]
I tried Array(4).fill(Array(4).fill(0)) but had the same result.
You could write a helper function to initialize your two dimensional array. For example:
const grid = (r, c) => Array(r).fill(null).map(r => Array(c).fill(null));
const g = grid(4, 4);
g[2][2] = 15;
console.log(g);
This was actually quite challenging to solve. I much prefer the accepted answer from fubar - however I thought I would add another possibility for some variance.
Pro: Doesn't obfuscate that you are dealing with an Array (like with the accepted answer).
Con: Hard to read.
var row = new Array(4).fill(0)
var block = new Array(4).fill(0).map(v => deepClone(row))
block[2][2] = 15
console.log(block);
function deepClone(array){return JSON.parse(JSON.stringify(array));}
How does this work? Well after you fill the array with blank values, .map is now able to iterate each and replace the value. In this case, it is a hacky deep clone of row thanks to the trusty ole JSON.parse.

Comparing similar objects of different instances in javascript

I had always wondered why this :
var a = [[0, 1]];
a[0] == [0, 1];
would return false. It seems like these 2 arrays, a[0] and [0, 1], despite not being the same instance of Array, ARE actually the same object, in so far as all their properties are the same. This is not the case in JS though and I don't know why.
Which test applied to these two arrays, and to much more complicated objects, would return true ? (answers from jQuery and D3.js are accepted, I don't plan on using any other)
Edit: wrapping the objects with JSON.stringify seems to work; are there any caveats I should be aware of though?
[Equal Operator] "If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory."
See: https://developer.mozilla.org/en/JavaScript/Reference/Operators/Comparison_Operators
So, even:
[0, 1] == [0, 1]
Will returns false, because they are different objects, even if with the same content.
If it's confuse you using the array literals, notice that the code above is exactly the same of the follow:
new Array(0, 1) == new Array(0, 1);
The two objects have the same value but are not the same object, for example if you push a new element to one the other will not get that new pushed element.
var a = [[0, 1]];
var b = [0, 1];
a[0].push(42);
alert(a[0].length); // now it's 3
alert(b.length); // still 2
Note also that the syntax [0, 1] is not representing an array object, but it's an array object "builder" that will produce a new fresh array each time it's evaluated:
function mkarr() {
return [0, 1];
}
var a = mkarr();
var b = mkarr();
a.push(42);
alert(a.length); // 3
alert(b.length); // still 2
alert(mkarr().length); // still 2 too
For numbers and strings instead equality matches because the referenced objects are immutable (i.e. you can make your variable to point to another number, but you cannot change the number itself).
Calling JSON.stringify on an object you get a string representation of the object, not the object... and the representations can indeed match equal for different objects (because they're just strings).
Note that the string representation doesn't really capture the object, and you can have substantially different objects with the same identical string representation... for example:
var a = [0, 1];
var b = [a, a];
var c = [[0, 1], [0, 1]];
alert(JSON.stringify(b) == JSON.stringify(c)); // true
b[0].push(42);
c[0].push(42);
alert(JSON.stringify(b)); // "[[0,1,42],[0,1,42]]"
alert(JSON.stringify(c)); // "[[0,1,42],[0,1]]"

Categories