Error parsing array through IF Statement - javascript

I need to loop through an entire 2D array (OldTable) to check that Column1 has a value of 1 and Col7 is not empty (null). If the above conditions are true then push the current (i) arrays of elements into newTable.
My snippet of JS is as follow...
var newTable = [];
for (var i=1; i<OldTable.length; i++){
if(OldTable[i][0]==1 && OldTable[i][7]!==null){
newTable.push(OldTable[i]);
}
}
Seems like a fairly straight forward thing to do but currently hitting brick wall with this error...
TypeError: Cannot read property "0" from undefined. (line 80, file
"Code"
I have tried to reduce the if statement to just...
if(OldTable[i][0]==1){
...but still the same error.
I'm able to display the array element just fine using...
Browser.msgBox(OldTable[50][0]);
I'm fairly new to JS so could be a simple silly error someone could point out.
UPDATE: In trying to simplying naming, I've actually made it more difficult with conflicting terminology, so have going through and updated the variable names used.

Your code should work if, as noted in the comment by #Massimo, you change your loop from starting at i=1 to i=0, as shown below. Also, just to whet your appetite for more modern tools within JavaScript, I also include an essentially identical solution to the problem using ES6/ES2015.
var myArray = [
[1, 0, 0, 0, 0, 0, 0, 'foo' ], // should pass
[9, 1, 1, 1, 1, 1, 1, 'foo' ], // should fail
[1, 2, 2, 2, 2, 2, 2, 'foo' ], // should pass
[1, 3, 3, 3, 3, 3, 3, null ], // should fail
[0, 4, 4, 4, 4, 4, 4, null ], // should fail
[1, 5, 5, 5, 5, 5, 5, undefined], // should pass
[1, 6, 6, 6, 6, 6, 6, 'foo' ] // should pass
];
function f1(array) {
var newArray = [];
for (var i = 0; i < array.length; i++) {
if (array[i][0] == 1 && array[i][7] !== null) {
newArray.push(array[i]);
}
}
return newArray;
}
const f2 = array => array.filter(e => e[0] === 1 && e[7] !== null);
console.log(f1(myArray));
console.log(f2(myArray));

Related

4th argument in reduce

Here is the function:
function chunk(array: number[], size: number): number[][] {
return array.reduce((chunks, curr, _, arr) => {
console.log(arr.length); // -> 10 which is correct
// let len = arr.length; // -> Cannot read properties of undefined (reading 'length')
let len = chunks.length; // this works
if (len === 0 || chunks[len - 1].length === size) chunks.push([curr]);
else chunks[len - 1].push(curr);
return chunks;
}, []);
}
console.log(chunk([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3)); // ->[ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ], [ 10 ] ]
The fourth argument to reduce is the array that we're iterating over. I can log it and I get the correct result (10) see above. But when I try to use it and assign it to a variable I get an error(see above). Could someone please shed some light?
From Mozilla's page, the fourth parameter is the array that is being reduced. You should access the array variable that is already declared, but the fourth parameter works.
For example:
array.reduce((_, __, ___, arr) => {
console.log(arr.length == array.length) // true, this is the source array
});
The reason why you're getting the error is not because of the arr.length property, but rather the way you're accessing chunks.

Problem with Mocha test when try to use the 'return' in the function

I am learning the Mocha test for js but have a weird problem an couldn't figure it out. Any big man can help me:
I do this test case:
it("remove all the number larger than 10", () => {
function filter(arr) {
return arr.filter(number => number < 11);
}
assert.equal(filter([1, 3, 3, 5, 10, 29, 3], [1, 3, 3, 5, 10, 3]));
});
But it returns undefined for that filter function, but when I remove the return keyword, it works fine:
it("remove all the number larger than 10", () => {
function filter(arr) {
arr.filter(number => number < 11);
}
assert.equal(filter([1, 3, 3, 5, 10, 29, 3], [1, 3, 3, 5, 10, 3]));
});
Can anyone can explain it to me?
Thanks
You've got a typo, your close paren ) for filter should be immediately after the first array instead of after both arrays.
Also, to compare arrays use assert.deepEqual instead of assert.equal:
it("remove all the number larger than 10", () => {
function filter(arr) {
return arr.filter(number => number < 11);
}
assert.deepEqual(filter([1, 3, 3, 5, 10, 29, 3]), [1, 3, 3, 5, 10, 3]); // SUCCESS
});
(The reason why it was passing when you removed the return keyword is that filter was being passed both arrays, then returning undefined. assert.equal was only being called with one argument so its second argument was implicitly undefined. Since undefined == undefined your test passed.)

Array with unique values using array helper functions

I was playing with ES6 array helper functions reduce() and find(). I'm trying to display array of unique elements. But it is failing in case of value 0. I'm not able to find what's wrong with my code. Please guide.
Here is my code snippet:
var arrayWithDuplicates = [0, 0, 1, 2, 3, 3, 4, 4, 'a', 'a'];
var arrayWithUniqueValues = arrayWithDuplicates
.reduce((previous, item) => {
if(!previous.find(element => element === item)) {
previous.push(item)
}
return previous;
}, []);
console.log('arrayWithUniqueValues', arrayWithUniqueValues)
I'm getting below output:
arrayWithUniqueValues [ 0, 0, 1, 2, 3, 4, 'a' ]
Why I'm getting 0 twice while all other values are unique?
You can achieve the same result by converting your array into a Set and back to an Array.
var arrayWithUniqueValues = [...new Set(arrayWithDuplicates)];
The reason your code doesn't work, by the way, is that Array.prototype.find returns the element it found. When you search for 0, it returns 0 and then !0 is true. So 0 is added even if it is already in the array. You can do instead:
if (previous.indexOf(item) === - 1) {
previous.push(item);
}
The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.
when you got 0,the code becomes :
arrayWithDuplicates.reduce(([0], 0) => {
if(!previous.find(element => element === item)) {
//![0].find(0=>0===0),return 0,so !0 means true
previous.push(item)
//so [0,0]
}
return previous;
});
a better way is
let a=[...new Set([0, 0, 1, 2, 3, 3, 4, 4, 'a', 'a'])];//[0, 1, 2, 3, 4, "a"]

How do I use reduce() to mimic the capabilities of forEach()?

I'm trying to accomplish a task with reduce() that I know how to do with forEach(). Unfortunately I'm not sure how to structure the syntax and I can't find a good example.
Example 1) In this code I use forEach() to insert the word species into the first index of each array.
"use strict";
var creatureArray;
creatureArray = [
['zombie', 30, 1, 'bite', 0, 5],
['skeleton', 10, 2, 'sword', 1, 10],
['orc', 15, 4, 'club', 1, 7]
];
creatureArray.forEach(function(value, index, array) {
array[index].unshift('species');
});
console.log(creatureArray);
Example 2) In this code I try to accomplish something similar using .reduce(). However I know that I'm missing a piece of syntax. I can't figure out how to apply the updated array to the accumulator which is then returned as an object. Thanks so much for any help!
"use strict";
var creatureArray, creatureObject;
creatureArray = [
['zombie', 30, 1, 'bite', 0, 5],
['skeleton', 10, 2, 'sword', 1, 10],
['orc', 15, 4, 'club', 1, 7]
];
creatureObject = creatureArray.reduce(function(accumulator, currentValue, index, array) {
array[index].unshift('species');
//what goes here?
return accumulator;
}, {});
console.log(creatureObject);
Here is how you can do accomplish it.
"use strict";
var creatureArray, creatureObject;
creatureArray = [
['zombie', 30, 1, 'bite', 0, 5],
['skeleton', 10, 2, 'sword', 1, 10],
['orc', 15, 4, 'club', 1, 7]
];
creatureObject = creatureArray.reduce((accumulator, currentValue) => {
return [...accumulator, ['species', ...currentValue]];
}, []);
console.log(creatureObject);
The ... syntax above is called the Spread Operator.
When applied it expands the elements of the array into the new array created by the enclosing [ and ], placing each element from the old array as a top level element into the new array. This results in a flat array instead of a nested array. E.g [[1, 2]] -> [[1, 2]], but [...[1, 2]] -> [1, 2].
This is highly useful because it enables both simple concatenation as well as insertion of top level elements either before or after the expanded array.
Consider:
"use strict";
const names = ['Linus', 'Jane', 'David'];
const withJakeAppended = [...names, 'Jake'];
const withJakePrepended = ['Jake', ...names];
[names, withJakeAppended, withJakePrepended].forEach(xs => console.log(xs));
As you can see, when we spread an Array it is not modified, so the pleasant syntax also enables improved ergonomics for immutable, value oriented programming.
Even better, ... works with Sets and Maps as well. In fact, it works any Iterable object, including ones we can create ourselves.
I might add that using the fourth argument to either Array.prototype.forEach or Array.prototype.forEach is a poor practice that should be avoided.
Note if you need to do this in a browser without ES2015 support, you can write
"use strict";
var creatureArray, creatureObject;
creatureArray = [
['zombie', 30, 1, 'bite', 0, 5],
['skeleton', 10, 2, 'sword', 1, 10],
['orc', 15, 4, 'club', 1, 7]
];
creatureObject = creatureArray.reduce(function (accumulator, currentValue) {
return accumulator.concat([['species'].concat(currentValue)]);
}, []);
console.log(creatureObject);
map is more apropriate in this case:
var creatureArray = [ ['zombie' , 30, 1, 'bite' , 0, 5],
['skeleton', 10, 2, 'sword', 1, 10],
['orc' , 15, 4, 'club' , 1, 7] ]
var creatureObject = creatureArray.map(currentValue => ['species', ...currentValue] )
console.log( JSON.stringify( creatureObject ).replace(/],/g, '],\n ') )

Are there limitations for nesting in Javascript? ("Error 21: Undefined is not an object" in Illustrator)

I'm using javascript with Adobe Illustrator CC 2015, and I'm trying to organize information about the artboards.
var myArt = {
types : {
type: "",
board : {
name : "",
refNum : 0,
chk : {}
}
}
};
//initialize
myArt.types = [0, 1, 2, 3, 4, 5, 6, 7, 8];
for (i=0; i<myArt.types.length; i++) {
myArt.types[i].board = [0, 1, 2, 3, 4, 5, 6, 7, 8];
for (j=0; j<myArt.types[0].board.length; j++) {
myArt.types[i].board[j].name = "";
}
};
I get Error 21: Undefined is not an object for the 2nd for loop.
As far as I can tell, what works for "types" should work for "board." The only difference I can see is that board is nested one level deeper. So I guess I'm wondering if there's some kind of limitation on nesting, or if there is some other problem that I'm not catching.
Your overriding myArt.types with an array of numbers. So in your second iteration when you are trying to do myArt.types[0].board.length you are actually calling 0.board.length,1.board.length, but 0.board is undefined. It looks like you are mixing up objects and arrays in javascript. Objects do not by default have a length property.
This is the data structure your loop is implying:
var myArt = {
types: [{
type: "",
board: [{name: "",refNum: 0,chk: {}}]
}]
};

Categories

Resources