Push object into array does not work as expected - javascript

My goal is to create an array like this:
[{"str":"a","number":1},{"str":"a","number":2},{"str":"b","number":1},{"str":"b","number":2}]
so I wrote this javascript
abc = ["a","b"]
num = [1,2]
arr = []
a = {}
for (var i in abc)
{
str = abc[i]
a.str = str;
for(var x in num)
{
number = num[x]
a.number = number
console.log(a)
arr.push(a)
}
}
the console log looks fine, but the array looks like this:
[{"str":"b","number":2},{"str":"b","number":2},{"str":"b","number":2},{"str":"b","number":2}]
Can anyone could explain this?

This is happening because you are actually working with a reference to the same object, thus modifying the same over and over.
To fix it you must declare a new object in every iteration you want to use a different one.
Try something like this:
var abc = ["a", "b"];
var num = [1, 2];
var arr = [];
for (var i in abc) {
for (var x in num) {
var a = {};
a.str = abc[i];
a.number = num[x];
arr.push(a);
}
}
console.log(arr);
Also, don't forget to declare your variables with var or let and end your statements with ;.

As said in the comments, you’ve pushed your a object to arr many times, instead of adding four separate objects. To fix this issue, you could declare a in the for (var x in num) loop, every time as a new object (using const or let). But I’ve simplified it further, see the code below.
To iterate through JavaScript arrays, you should use .forEach method.
let abc = ['a', 'b'];
let num = [1, 2];
let arr = [];
abc.forEach(letter => {
num.forEach(number => {
arr.push({number: number, str: letter});
});
});

abc = ["a","b"]
num = [1,2]
arr = []
for (var i in abc)
{
for(var x in num)
{
a = {} ---------------- Reset "a"
str = abc[i] --------------------- 1
a.str = str; --------------------- 2
number = num[x]
a.number = number
console.log(a)
arr.push(a)
}
}
console.log(arr)
// Move 1 and 2 inside the second loop

Using map :
let tempArray = abc.map((e,i) => { return num.map((ee,ii) => { return {"str": e, "number": ee }; } ) });
$.merge(tempArray[0], tempArray[1]);

Related

A function that returns an array which is the intersection of two other arrays

function arraysCommon(array1, array2) {
return array1.filter(x => array2.includes(x));
}
This function does not work the way I want it to.
For instance given array1 = [1,2,3,2,1] and array2 = [5,4,3,2,1]
it returns [1,2,3,2,1], since the elements 1,2,3 are seen in both arrays.
But I want it to return [1,2,3] in that order since 1,2,3 are seen only once in array2 and are treated as seperate entities.
So pretty much the functionality should be that
Each element in the first array can map to at most one element in the second array.
Duplicated elements in each array are treated as separate entities.
the first array determines the order
I have attempted to loop through the arrays and check and compare the number of duplicates in each array but I can't seem to get the logic working correctly. Is there a different way to approach this?
I've attached an image of two Venn diagrams that might clarify the difference
Unfortunately, it gets more complicated because you need to know what numbers you have already added. In this case you need a temporary array to hold the result. We also need to track if a number exists in the array two times.
Try this:
function arraysCommon(array1, array2) {
//Copy array2 by duplicating and spreading the elements into another array.
var copyArray2 = [...array2];
//Temperary Array
var temp = [];
for (let x of array1) {
//Check if the element is in the first array and not already added to the temp array
if (copyArray2.includes(x)) {
temp.push(x);
//Remove item from copy array2 so it cannot be used anymore
copyArray2.splice(copyArray2.indexOf(x), 1);
}
}
//Return the temp array
return temp;
}
console.log(arraysCommon([1,2,3,2,1], [5,4,3,2,1]))
console.log(arraysCommon([1,2,3,2,1], [2,2,3,3,4]))
With sorting and counting this should be possible. Since you are incrementing when you find similar characters, this should be okay:
const array1= [1,4,1,1,5,9,2,7];
const array2 = [1,8,2,5,1]
const array3 = [1,2,3,2,1];
const array4 = [5,4,3,2,1,2]
const array5 = [1,2,3,2,1];
const array6 = [2,2,3,3,4]
function arraysCommon(array1, array2) {
const ans = [];
array1.sort();
array2.sort();
let j = 0;
let i = 0;
while(i<array1.length && j<array2.length){
if(array1[i] === array2[j]){
ans.push(array1[i]);
i++;
j++;
}
else if(array2[i] > array1[j]){
i++;
}
else{
j++;
}
}
console.log(ans);
}
arraysCommon(array1,array2);
arraysCommon(array3,array4);
arraysCommon(array5,array6);
this should work as you wanted!
// test 1
const array1 = [1,4,1,1,5,9,2,7];
const array2 = [1,8,2,5,1];
// test 2
const array3 = [1,2,3,2,1];
const array4 = [5,4,3,2,1];
const mapper = (array1, array2) => {
var obj = {};
array1.forEach((x, indexX) => {
array2.forEach((y, indexY) => {
if (x == y) {
if (!Object.values(obj).includes(indexX) && !obj.hasOwnProperty(indexY)) {
obj[indexY] = indexX;
return;
}
}
})
})
return Object.values(obj).sort().map(values => array1[values]);
}
console.log(mapper(array1, array2));
console.log(mapper(array3, array4));
I hope this helps. Cheers.
You can instance a new Set, wich brings only unique values and than retorn a array from this set.
Something like this:
function arraysCommon(array1, array2) {
const filtered = array1.filter(x => array2.includes(x));
const uniqueValues = new Set(filtered)
return Array.from(uniqueValues)
}

JavaScript - input array changed without push statement

I was on leet code #283
Given an array nums, write a function to move all 0's to the end of it
while maintaining the relative order of the non-zero elements.
Input: [0,1,0,3,12]
Output: [1,3,12,0,0]
Can somebody please explain the following code.
var moveZeroes = function(nums) { // nums is [0,1,0,3,12]
var len = nums.length;
for (let lastNonZero = 0, cur = 0; cur < len; cur++) {
if (nums[cur] !== 0) {
[nums[lastNonZero], nums[cur]] = [nums[cur], nums[lastNonZero]]; // what exactly happened here
lastNonZero++;
}
}
return nums;
};
How did the for loop work and how is the nums array rearranged?
The line: [nums[lastNonZero], nums[cur]] = [nums[cur], nums[lastNonZero]] is just replacement. If you have [1, 2] and use this code, you'll end up with [2, 1]. The function you provided will run through the loop and move 0 to the right and the next number to the left, until it gets to [0, 0].
I believe The following
[nums[lastNonZero], nums[cur]] = [nums[cur], nums[lastNonZero]];
is short for
nums[lastNonZero] = nums[cur];
// and
nums[cur] = nums[lastNonZero];
but simultaneously with out doing
const tempCurrent = nums[cur];
const tempLastNonZero = nums[lastNonZero];
nums[lastNonZero] = tempCurrent;
nums[cur] = tempLastNonZero;
Edit:
destructuring is the name of this syntax thanks to #SanthoshN
destructuring assignment from #gaetanoM and #Jacque Goupil is what that is
[nums[lastNonZero], nums[cur]] = [nums[cur], nums[lastNonZero]];
This is a es6 syntax called de de-structuring, whats happening there is a just a swap.
example of object destructuring
obj = { 'a': 1, 'b': 2}
const { a, b } = obj;
instead of accessing obj.a everywhere you can now just use a, which is destructed as local variable.
similarly lets consider an array
arr = [1,2,3];
const [a,b,c] = arr;
console.log(a) will result in 1;
Essentially, the first element in the array is assigned to the first variable int the array.
Hope it clarifies.
[nums[lastNonZero], nums[cur]] = [nums[cur], nums[lastNonZero]] just do swapping.
let [a,b] = ['b','a']
console.log(a,b)
Alternate method is to use filter and concat.
Here idea is
By filter we take all non zero element in a variable.
Add number of zero equal to length of original arr - filtered arr
let arr = [1,2,3,0,15,10,82,19,0,5,8,7]
let op = arr.filter(e=>e)
let final = op.concat(new Array(arr.length - op.length).fill(0))
console.log(final)

Integer arrays comparison

I have a question of JS arrays.
Example:
var fullArr = [1,2,3,4];
var partArr = [2,3];
var newArr = [];
We have a main array fullArr and a partial array partarr. I want to create a function/filter, which is looking for existing items in fullArr and not in partArr.
In this example above newArr must be equal to [1,4].
I've tried doing something like this, but it's not working properly.
for (var k in fullArray) { // [1,2,3,4]
for (var j in selectedArray) { // [1,4]
if (fullArray[k] == selectedArray[j]) {
newArray.splice(selectedArray[j] - 1, 1); // must be [2,3]
break;
}
}
}
What is a good way of making this? Thanks.
Here's one
var newArr = fullArr.filter(function(f) { // The filter() method creates a new array with all elements that pass the test implemented by the provided function.
return partArr.indexOf(f) == -1; // The indexOf() method returns the first index at which a given element can be found in the array, or -1 if it is not present.
})
to impress the girls, you can also
var newArr = fullArr.filter(function(f) {
return !~partArr.indexOf(f);
})
Here is the code for your requirement.
var fullArr = [1,2,3,4];
var partArr = [2,3];
var newArr = [];
for(var i=0;i<fullArr.length;i++){
if(partArr.indexOf(fullArr[i]) == -1)
newArr.push(fullArr[i]);
};
Here is the working Link
Hope it works :)
In fact, you want a common part between arrays. Obviously you can choose splice or indexOf to have O(n * m) or even O(m * n^2) performance. It's obviously suboptimal for any array larger than few elements
Or you can use objects as hash maps to find differences in (in worst case) O(n + m log m):
var fullArr = [1,2,3,4];
var partArr = [2,3];
var temporaryObject = Object.create(null);
partArr.forEach(el=>temporaryObject[el] = true); // temporaryObject after this operation is {"2": true, "3": true}
var newArr = fullArr.filter(el=>temporaryObject[el]);
In this example I have used ES6 feature called "arrow functions". It translates to following ES5 code:
var partArr = [2, 3];
var temporaryObject = Object.create(null);
partArr.forEach(function (el) {
temporaryObject[el] = true;
}); // temporaryObject after this operation is {"2": true, "3": true}
var newArr = fullArr.filter(function (el) {
return temporaryObject[el];
});
You can use the filter() function that works on arrays:
var newArr = fullArr.filter(function(val, i, arr) {
return partArr.indexOf(val) === -1;
});
This will return a new array containing the values of every iteration that returns true.
Should you ever need to do this on an object in the future a great way is to first convert the object keys to an array and then run the filter:
Object.keys(myObj).function(val, i, arr) {
return partArr.indexOf(val) === -1;
});
Here are few other approaches:
var fullArr = [1,2,3,4];
var partArr = [2,3];
var newArr = [];
1.
fullArr.map(function(element){
if(partArr.indexOf(element) === -1) newArr.push(element);
})
console.log(newArr);
2.
for(i in fullArr){
if(partArr.indexOf(fullArr[i]) === -1) newArr.push(fullArr[i]);
}
console.log(newArr);
3.
fullArr.forEach(function(element){
if(partArr.indexOf(element) === -1) newArr.push(element);
})
console.log(newArr);

Javascript merge 2 arrays and sum same key values

I have 2 array:
var array1 = [[5,10],[6,10],[7,10],[8,10],[9,10]];
var array2 = [[1,10],[2,10],[3,10],[4,10],[5,40],[6,40]];
Want to get 1 merged array with the sum of corresponding keys;
var array1 = [[1,10],[2,10],[3,10],[4,10],[5,50],[6,50],[7,10],[8,10],[9,10]];
Both arrays have unique keys, but the corresponding keys needs to be summed.
I tried loops, concat, etc but can't get the result i need.
anybody done this before?
You can use .reduce() to pass along an object that tracks the found sets, and does the addition.
DEMO: http://jsfiddle.net/aUXLV/
var array1 = [[5,10],[6,10],[7,10],[8,10],[9,10]];
var array2 = [[1,10],[2,10],[3,10],[4,10],[5,40],[6,40]];
var result =
array1.concat(array2)
.reduce(function(ob, ar) {
if (!(ar[0] in ob.nums)) {
ob.nums[ar[0]] = ar
ob.result.push(ar)
} else
ob.nums[ar[0]][1] += ar[1]
return ob
}, {nums:{}, result:[]}).result
If you need the result to be sorted, then add this to the end:
.sort(function(a,b) {
return a[0] - b[0];
})
This is one way to do it:
var sums = {}; // will keep a map of number => sum
// for each input array (insert as many as you like)
[array1, array2].forEach(function(array) {
//for each pair in that array
array.forEach(function(pair) {
// increase the appropriate sum
sums[pair[0]] = pair[1] + (sums[pair[0]] || 0);
});
});
// now transform the object sums back into an array of pairs
var results = [];
for(var key in sums) {
results.push([key, sums[key]]);
}
See it in action.
a short routine can be coded using [].map()
var array1 = [[5,10],[6,10],[7,10],[8,10],[9,10]];
var array2 = [[1,10],[2,10],[3,10],[4,10],[5,40],[6,40]];
array1=array2.concat(array1).map(function(a){
var v=this[a[0]]=this[a[0]]||[a[0]];
v[1]=(v[1]||0)+a[1];
return this;
},[])[0].slice(1);
alert(JSON.stringify(array1));
//shows: [[1,10],[2,10],[3,10],[4,10],[5,50],[6,50],[7,10],[8,10],[9,10]]
i like how it's just 3 line of code, doesn't need any internal function calls like push() or sort() or even an if() statement.
Try this:
var array1 = [[5,10],[6,10],[7,10],[8,10],[9,10]];
var array2 = [[1,10],[2,10],[3,10],[4,10],[5,40],[6,40]];
var res = [];
someReasonableName(array1, res);
someReasonableName(array2, res);
function someReasonableName(arr, res) {
var arrLen = arr.length
, i = 0
;
for(i; i < arrLen; i++) {
var ar = arr[i]
, index = ar[0]
, value = ar[1]
;
if(!res[index]) {
res[index] = [index, 0];
}
res[index][1] += value;
}
}
console.log(JSON.stringify(res, null, 2));
So, the result may have holes. Just like 0th index. Use the below function if you want to ensure there are no holes.
function compact(arr) {
var i = 0
, arrLen = arr.length
, res = []
;
for(i; i < arrLen; i++) {
var v = arr[i]
;
if(v) {
res[res.length] = v;
}
}
return res;
}
So, you can do:
var holesRemoved = compact(res);
And finally if you don't want the 0th elem of res. Do res.shift();
Disclaimer: I am not good with giving reasonable names.
The simple solution is like this.
function sumArrays(...arrays) {
const n = arrays.reduce((max, xs) => Math.max(max, xs.length), 0);
const result = Array.from({ length: n });
return result.map((_, i) => arrays.map(xs => xs[i] || 0).reduce((sum, x) => sum + x, 0));
}
console.log(...sumArrays([0, 1, 2], [1, 2, 3, 4], [1, 2])); // 2 5 5 4

Functional approach to basic array construction

This is my code, acting upon myArray:
var myArray = [];
var i;
for(i = 0; i < 20; i += 1) {
myArray.push(Math.random());
}
Is there a functional equivalent of the above that does without the dummy variable i?
Favorite answers:
while(myArray.push(Math.random()) < 20);
$.map(Array(20), Math.random);
for(var myArray = []; myArray.push(Math.random()) < 20;);
Not in ES5, there's no real functional equivalent to it, as you have to have something which has an amount of 20 to apply map to...
var my20ElementArray = [0,1,2,3,4,5,6,7,8,9,10];
var myArray = my20ElementArray.map(Math.random);
You could create an xrange-like function what is in Python but that would just hide this "unused" variable inside a function.
With JavaScript 1.7, you can use Array comprehensions for this task:
var myArray = [Math.random() for each (i in range(0, 20))];
However, with ES5.1 you can just use the Array constructor to generate an array of arbitrary length, and then map it to random numbers. Only drawback is that map() does not work with uninitialised values, so I first generate an Array of empty strings by using join and split:
var myArray = new Array(20).join(" ").split(" ").map(Math.random);
Ugly, but short. A maybe better (but less understandable) idea from Creating range in JavaScript - strange syntax:
var myArray = Array.apply(null, {length: 20}).map(Math.random);
Starting with #FelixKlings comment, one could also use this one-liner without the i loop variable:
for (var myArray=[]; myArray.push(Math.random()) < 20;);
// much better:
for (var myArray=[]; myArray.length < 20;) myArray.push(Math.random());
Are you looking for something as follows:
function makeArray(length, def) {
var array = [];
var funct = typeof def === "function";
while (array.push(funct ? def() : def) < length);
return array;
}
Then you can create arrays as follows:
var array = makeArray(100); // an array of 100 elements
var zero = makeArray(5, 0); // an array of 5 `0`s
In your case you may do something like:
var myArray = makeArray(20, Math.random);
See the following fiddle: http://jsfiddle.net/WxtkF/3/
how about this?
it's functionale style and it's very concise.
var makeRandomArray = function(n){
if (n == 0) return [];
return [Math.random()].concat(makeRandomArray(n-1));
};
console.log(makeRandomArray(20))
http://jsfiddle.net/YQqGP/
​
You could try:
var myArray = String(Array(20)).split(',')
.map( () => Math.random() );
Or extend the Array prototype with something like:
Array.prototype.vector = function(n,fn){
fn = fn || function(){return '0';};
while (n--){
this.push(fn());
}
return this;
}
// usage
var myArray = [].vector(20, () => Math.random());
Or try something funny:
var myArray = function a(n,fn){
return n ? a(n-1,fn).concat(fn()) : [];
}(20, () => Math.random())
Or use Array.from (ES>=2015)
Array.from({length: 20}).map(() => Math.random())

Categories