Duplicate one array of objects in multiple arrays - javascript

I want to duplicate one array of objects into multiple ones, because every one of them I need to use in separate places.
if(!this.tempLookups){
for (let count = 0; count < this.dates.length; count++) {
this.tempLookups[count] = this.lookups[key];
}
}
Error: Uncaught (in promise) TypeError: Cannot set property '0' of null

The actual reason for the error is clearly in error message that you are trying to set the property for a null. So in order to fix simply define it after the if.
if(!this.tempLookups){
his.tempLookups = [];
for (let count = 0; count < this.dates.length; count++) {
this.tempLookups[count] = this.lookups[key];
}
}
You can do it in a single line without a for loop using Array#fill method since you are filling with the same value.
if(!this.tempLookups){
this.tempLookups = new Array(this.dates.length).fill(this.lookups[key]);
}

You can do this like this:
if (!this.tempLookups) {
this.tempLookups = [];
for (let i = 0; i < this.dates.length; i++) {
this.tempLookups.push(Array.from(this.lookups[key]));
}
}
Note that the this.tempLookups variable is initialized as empty array before we start inserting data. The Array.from call in for loop makes sure we actually create (shallow) copies of the this.lookups[key] array, instead of just assigning reference to the same this.lookups[key] array multiple times. Without Array.from changing one array would change all of them - because in reality there would be only one array referenced multiple times.

Related

Custom array function for MIN() in Google Sheets

Since the MIN() function in Sheets only returns a single value and there is no way to make it work with ARRAYFORMULA, I wanted to make a custom function that would take two arrays and compare the values at each entry, and return an array of the minimums. (I know there's a workaround that uses QUERY, but it wasn't going to work for my purposes)
What I have right now will take two arrays with one row and work perfectly. Unfortunately, it breaks when more than one row is introduced. I'm not sure why, so I'm lost on how to move forward. How can I make it work for any size arrays?
When I feed it any two dimensional range, it throws an error:
"TypeError: Cannot set property '0' of undefined"
on this line finalarray[x][y] = Math.min(arr1[x][y], arr2[x][y]);
The current ""working"" code:
function MINARRAY(arr1, arr2) {
if (arr1.length == arr2.length && arr1[0].length == arr2[0].length)
{
var finalarray = [[]];
for (x = 0; x < arr1.length; x++)
{
for(y = 0; y < arr1[x].length; y++)
{
finalarray[x][y] = Math.min(arr1[x][y], arr2[x][y]);
}
}
return finalarray;
}
else
{
throw new Error("These arrays are different sizes");
}
}
finalarray is a 2D array. [[]] sets only the first element of finalarray to a array. It is needed to set all elements of finalarray to a array. Inside the loop, add
finalarray[x]=[]//set `x`th element as a array or finalarray[x]= finalarray[x] || []
finalarray[x][y] = Math.min(arr1[x][y], arr2[x][y]);
Alternatively,
finalarray[x] = [Math.min(arr1[x][y], arr2[x][y])]

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.

Looping data in javascript

How can I get the value BrandName in this image using javascript loop.
UPDATED: Since data variable you use to display the response is already a CartObject then use:
for (var i = 0, len = data.CartLists.length; i < len; i++) {
console.log( data.CartLists[i].Item.BrandName );
}
An alternative to the one VisioN said is the following:
for (var CartItemId in CartObject.CartLists) {
Console.log(CartObject.CartLists[CartItemId].Item.BrandName);
}
However, If you would attach an Prototype to the JSON object, you could obtain an Object in the for-loop instead of an Integer (Number).
for (var CartItem in CartObject.CarLists) {
Console.log(CartItem.Item.BrandName);
}
Note that if you are going to make everything right, you should insert the following in the for-loop:
if (CartObject.CarLists.hasOwnProperty(CartItem)) {
Console.log(CartItem.Item.BrandName);
}
This example will work, but as seen in the comments below. The use of it is not what it is designed for. The For-In loop is designed to loop over Object properties, not Array items.

Removing Multiple Objects from Javascript Array Breaks Half Way Through

I have an Array of a few hundred JSON Objects...
var self.collection = [Object, Object, Object, Object, Object, Object…]
Each one looks like this...
0: Object
id: "25093712"
name: "John Haberstich"
I'm iterating through the Array searching each Array.id to see if it matches any ids in a second Array...
var fbContactIDs = ["1072980313", "2502342", "2509374", "2524864", "2531941"]
$.each(self.collection, function(index, k) {
if (fbContactIDs.indexOf(k.id) > -1) {
self.collection.splice(index, 1);
};
});
However this code only works to splice three of the Objects from the self.collection array and then it breaks and gives the following error:
Uncaught TypeError: Cannot read property 'id' of undefined
The line that is causing the error is this one...
if (fbContactIDs.indexOf(k.id) > -1) {
Could anyone tell me what I'm dong wrong here?
Because the length of collection will change, the trick is to loop from rear to front
for (var index = self.collection.length - 1; index >= 0; index--) {
k = self.collection[index];
if (fbContactIDs.indexOf(k.id) > -1) {
self.collection.splice(index, 1);
};
}
You should not change the length of an array while iterating over it.
What you're trying to do is filtering and there's a specific function for that. For example:
[1,2,3,4,5,6,7,8,9,10].filter(function(x){ return (x&1) == 0; })
will return only even numbers.
In your case the solution could then simply be:
self.collection = self.collection.filter(function(k){
return fbContactIDs.indexOf(k.id) > -1;
});
or, if others are keeping a reference to self.collection and you need to mutate it inplace:
self.collection.splice(0, self.collection.length,
self.collection.filter(function(k){
return fbContactIDs.indexOf(k.id) > -1;
}));
If for some reason you like to process elements one at a time instead of using filter and you need to do this inplace a simple approach is the read-write one:
var wp = 0; // Write ptr
for (var rp=0; rp<L.length; rp++) {
if (... i want to keep L[x] ...) {
L[wp++] = L[rp];
}
}
L.splice(wp);
removing elements from an array one at a time is an O(n**2) operation (because for each element you remove also all the following ones must be slided down a place), the read-write approach is instead O(n).

Why is the JS Array skipping certain entries when running the splice method within a loop?

I have an array:
var productIds = new Array("1","6","7","Product-Total","ccFirst","ccLast","email","ccExpMonth","ccExpYear","billingAddress","billingCity","billingState","billingZip");
I want to delete a value if it is not a number:
for(var i=0; i<productIds.length; i++){
if(isNaN(Number(productIds[i]))) {
productIds.splice(i,1);
}
}
It seems the splice method is affecting the positions of the values.
I found this solution(Looping through array and removing items, without breaking for loop) which is what I think I need, but I can't figure out how to implement their answers for my code.
How can I fix my problem?
btw, I posted a more detailed jsFiddle: http://jsfiddle.net/fte3m/2/
When you delete the entry at index i, you need to subtract 1 from i so the entry that was moved down is not skipped.
for(var i=0; i<productIds.length; i++){
if(isNaN(productIds[i])) {
productIds.splice(i--,1); // <-- Decrement i
}
}
As RobG points out in his comment, it's easier to simply process the array in the other direction:
for(var i=productIds.length - 1; i>=0; i--){
if(isNaN(productIds[i])) {
productIds.splice(i,1);
}
}
Alternatively, if you don't mind reassigning productIds to be a new array object and you are running JS 1.6 or later:
productIds = productIds.filter(function (id) {
return !isNaN(id);
});
(Note that in the above, I just use isNaN(value) rather than isNaN(Number(value)). Whenever Number(value) would return NaN, isNaN(value) will return true, and vice versa. Note also that neither approach will filter out a null id, since Number(null)==0 and isNaN(null)==false. If you want to exclude null entries from the result, you will need to test for that separately.)

Categories