I want to replace the number in the myArray to either 'even' or 'odd' but it throws an error that TypeError: val.replace is not a function
const myArray = [
[23, 156, 25, 10, 52, 23],
[12, 100, 23, 56, 81, 93],
[42.5, 71, 10, 23, 35, 11, 72, 99],
[11, 100, 99, 102, 13, 8, 12]
];
let arr = myArray.map(item => {
return item.map(val => {
if (val % 2 == 0) {
val.toString();
val.replace(val, "even");
} else {
val.replace(val, "odd");
}
});
});
console.log(arr); //TypeError: val.replace is not a function
You need to return the new value.
String#replace returns a new string with the replaced values, but you do not have a strings here.
const myArray = [
[23, 156, 25, 10, 52, 23],
[12, 100, 23, 56, 81, 93],
[42.5, 71, 10, 23, 35, 11, 72, 99],
[11, 100, 99, 102, 13, 8, 12]
];
let arr = myArray.map(item => {
return item.map(val => {
if (val % 2 == 0) {
return "even";
} else {
return "odd";
}
});
});
console.log(arr);
You don't need to use replace, you simply need to map
const myArray = [
[23, 156, 25, 10, 52, 23],
[12, 100, 23, 56, 81, 93],
[42.5, 71, 10, 23, 35, 11, 72, 99],
[11, 100, 99, 102, 13, 8, 12]
];
let arr = myArray.map(item => item.map(val => val % 2 == 0 ? 'even' : 'odd'))
console.log(arr);
You can try following (Check for value if divisible by 0, if yes return even else odd)
const myArray = [[23, 156, 25, 10, 52, 23], [12, 100, 23, 56, 81, 93], [42.5, 71, 10, 23, 35, 11, 72, 99], [11, 100, 99, 102, 13, 8, 12]];
let arr = myArray.map(item => item.map(val => val%2 === 0 ? "even": "odd"));
console.log(arr);
Or you can improve your code as follows
const myArray = [[23, 156, 25, 10, 52, 23], [12, 100, 23, 56, 81, 93], [42.5, 71, 10, 23, 35, 11, 72, 99], [11, 100, 99, 102, 13, 8, 12]];
let arr = myArray.map(item => {
return item.map(val => {
if (val % 2 == 0) {
val = val.toString(); // you need to reassign after toString
val = val.replace(val, "even"); // you need to reassign after replace
} else {
val = val.toString(); // you need to reassign after toString
val = val.replace(val, "odd"); // you need to reassign after replace
}
return val; // finally you need to return the updated value
});
});
console.log(arr); //Now the right input will be logged
Related
Let's say we want to count the NaN's in a javascript array. We can use
let arr = [...Array(100)].map( (a,i) => i %10==0 ? NaN : i )
console.log(arr)
> [NaN, 1, 2, 3, 4, 5, 6, 7, 8, 9, NaN, 11, 12, 13, 14, 15, 16, 17, 18, 19, NaN, 21, 22, 23, 24, 25, 26, 27, 28, 29, NaN, 31, 32, 33, 34, 35, 36, 37, 38, 39, NaN, 41, 42, 43, 44, 45, 46, 47, 48, 49, NaN, 51, 52, 53, 54, 55, 56, 57, 58, 59, NaN, 61, 62, 63, 64, 65, 66, 67, 68, 69, NaN, 71, 72, 73, 74, 75, 76, 77, 78, 79, NaN, 81, 82, 83, 84, 85, 86, 87, 88, 89, NaN, 91, 92, 93, 94, 95, 96, 97, 98, 99]
let nans = arr.map( aa => isNaN(aa) ? 1 : 0).reduce((acc,a) => acc+a)
console.log(nans)
> 10
That does work.. but it is a bit challenging to remember the reduce() machinery every time. Is there a more concise construct by applying a predicate as so:
arr.count( a => isNan(a))
You can have just a single .reduce where the accumulator is the number of NaNs found so far:
const arr = [...Array(100)].map( (a,i) => i %10==0 ? NaN : i );
const nans = arr.reduce((a, item) => a + isNaN(item), 0);
console.log(nans);
You can filter out the elements that are not NaN.
arr.filter(isNaN).length
//or
arr.filter(function(it){ return isNaN(it); }).length
With forEach loop instead of map and reduce
const nanCount = (arr, count = 0) => (
arr.forEach((num) => (count += isNaN(num))), count
);
const arr = [NaN, 0, 1, 3 , NaN];
console.log(nanCount(arr));
Or while for even bigger...
const arr = [...Array(1e6)].map((a, i) => i % 10 == 0 ? NaN : i);
let
i = arr.length,
nans = 0;
while (i--) {
nans += isNaN(arr[i]);
}
console.log(nans.toExponential());
const arr = [...Array(100)].map((a, i) => i % 10 == 0 ? NaN : i);
const count = (arr, predicate) => {
let c = 0, i = arr.length;
while (i--) c += predicate(arr[i]);
return c
};
const
nans = count(arr, x => isNaN(x)),
sevens = count(arr, x => x % 7 === 0);
console.log(`nans: ${nans}, sevens: ${sevens}`);
I have a function that should take an (n*n) grid as an argument and output the maximum product of 4 nos. of all rows. (A part of project Euler problem 11). When I try to run the code it gives me,
TypeError: Cannot read property 'length' of undefined
What am I doing wrong here? (I am a beginner so plz tell me if I have any silly mistakes.)
Here is my code:
const grid = [
[40, 17, 81, 18, 57],
[74, 4, 36, 16, 29],
[36, 42, 69, 73, 45],
[51, 54, 69, 16, 92],
[7, 97, 57, 32, 16]
];
function largestGridProduct(arr) {
let product = 1 , maxProduct = 1;
for(let i=0 ; i<arr.length ; i++){
for(let j=0 ; j<arr.length-3 ; j++){
product = grid[i][j] * grid[i][j+1] * grid[i][j+2] * grid[i][j+3];
if(product > maxProduct){
maxProduct = product;
}
}
}
return maxProduct;
}
console.log(largestGridProduct(grid));
So what am i doing wrong here ?
You're not returning anything in the function...
By the way, you can make it easier.
See this:
[
[40, 17, 81, 18, 57],
[74, 4, 36, 16, 29],
[36, 42, 69, 73, 45],
[51, 54, 69, 16, 92],
[7, 97, 57, 32, 16]
].reduce((max, a2) => {
const val = a2.reduce((a, b) => {
return Math.max(a, b);
});
return Math.max(val, max);
}, 0)
It's using arrow functions (es6) and array reduce. This returns the max of all the input arrays.
It was a silly mistake I was using variable name 'grid' instead of 'arr' inside the function.
BTW thanks everyone.
Ok.Here is my working code :-
const grid = [
[40, 17, 81, 18, 57],
[74, 4, 36, 16, 29],
[36, 42, 69, 73, 45],
[51, 54, 69, 16, 92],
[7, 97, 57, 32, 16]
];
function largestGridProduct(arr) {
let product = 1 , maxProduct = 1;
for(let i=0 ; i<arr.length ; i++){
for(let j=0 ; j<arr.length-3 ; j++){
product = arr[i][j] * arr[i][j+1] * arr[i][j+2] * arr[i][j+3];
if(product > maxProduct){
maxProduct = product;
}
}
}
return maxProduct;
}
console.log(largestGridProduct(grid));
working like this :)
if(product > maxProduct){
return product = maxProduct;
}
return maxProduct;
}
}
}
How does the for in loop work below to correctly sort the numbers in the left array and right array for the quick sort implementation below?
I'd like an example of a first example iteration of the sortArr(left) recursive call, then another iteration, and so on (maybe up to three or four iterations).
Then I'll be able to understand the sortArr(left), including the sortArr(right) recursive call.
const unsortedArr = [31, 27, 28, 42, 13, 8, 11, 30, 17, 41, 15, 43, 1, 36, 9, 16, 20, 35, 48, 37, 7, 26, 34, 21, 22, 6, 29, 32, 49, 10, 12, 19, 24, 38, 5, 14, 44, 40, 3, 50, 46, 25, 18, 33, 47, 4, 45, 39, 23, 2];
let sortArr = (arr) => {
if (arr.length < 2) return arr;
const pivot = arr[Math.floor(arr.length / 2)];
let left = [];
let equal = [];
let right = [];
equal.push(pivot);
for (let element of arr) {
if (element < pivot) {
left.push(element);
} else if (element > pivot) {
right.push(element);
}
}
let sortedArr = sortArr(left)
.concat(equal)
.concat(sortArr(right));
return sortedArr;
};
console.log(sortArr(unsortedArr));
I'm trying to create a bot that interprets an array (exp table) and returns the exp difference between two levels.
I'm new to JavaScript still, so I'm sure it's something within my code, I have tried various combinations of array.find, array[x] and moving formula into variables. I just cannot seem to figure it out.
var xparray = [1, 0, 2, 300, 3, 900, 4, 2000, 5, 3700, 6, 6000, 7, 10200, 8, 16200, 9, 23550, 10, 33480, 11, 45280, 12, 60880, 13, 80480, 14, 104180, 15, 130580, 16, 161080, 17, 196480, 18, 236980, 19, 282680, 20, 333680, 21, 390280, 22, 454180, 23, 525580, 24, 604680, 25, 691780, 26, 786980, 27, 896780, 28, 1021580, 29, 1161780, 30, 1317680, 31, 1480180, 32, 1656080, 33, 1845680, 34, 2049180, 35, 2267080, 36, 2499400, 37, 2749300, 38, 3017100, 39, 3303300, 40, 3608200, 41, 3932200, 42, 4272400, 43, 4629200, 44, 5002900, 45, 5393700, 46, 5801900, 47, 6239500, 48, 6707000, 49, 7205000, 50, 7734000, 51, 8598000, 52, 9656400, 53, 10923600, 54, 12478800, 55, 14350800, 56, 16568400, 57, 19160400, 58, 22155600, 59, 25582800, 60, 29470800, 61, 33940800, 62, 38813800, 63, 44129800, 64, 49938800, 65, 56302800, 66, 63297800, 67, 71019800, 68, 79594800, 69, 89187800, 70, 100013800, 71, 112462800, 72, 126343800, 73, 141899800, 74, 159398400, 75, 179148400, 76, 201478400, 77, 226818400, 78, 255468400, 79, 288218400, 80, 325868400];
var tn = (String(message).length);
// !xp 40 60
var a = (String(message).length)-3;
var b = (String(message).length)-3;
var c = (String(message).length)-5;
var d = (String(message).length)-2;
var t0 = message.substring(b, a); //(-3,-3)
var t1 = message.substring(c, b); //(-5,-3)
var t2 = message.substring(d, tn); //(-2,0)
var na = function(t0){return (t0*2)-1};
var nb = function(t1){return (t1*2)-1};
var nc = function(t2){return (t2*2)-1};
var T1 = xparray.find(function(element) {
return element > t2});
var T2 = xparray.find(function(element) {
return element > t0;
});
var T3 = xparray.find(function(element) {
return element > t1;
});
var t3 = function(T1, T2, T3) {
if (message.length = 7) {
return T1 - T2;
} else {
return T1 - T3;
}
};`
I expect this to pull values 40 and 60 from the end of the string '!xp 40 60', interpret the array and pull the next value after 40 (3608200) and the value after 60 (29470800), then preform a calculation to take the 40 value away from the 60 value (29470800-3608200). So far I think the issue lies around the T1, T2 and T3 values as they are always returning 1, or the value in the array after 1 (300).
With one dimensional array:
You can just get the index of the lvl in the array with indexOf and then take the next value (which is the xp needed for that lvl). After that subtract the two and you are good to go:
var xparray = [1, 0, 2, 300, 3, 900, 4, 2000, 5, 3700, 6, 6000, 7, 10200, 8, 16200, 9, 23550, 10, 33480, 11, 45280, 12, 60880, 13, 80480, 14, 104180, 15, 130580, 16, 161080, 17, 196480, 18, 236980, 19, 282680, 20, 333680, 21, 390280, 22, 454180, 23, 525580, 24, 604680, 25, 691780, 26, 786980, 27, 896780, 28, 1021580, 29, 1161780, 30, 1317680, 31, 1480180, 32, 1656080, 33, 1845680, 34, 2049180, 35, 2267080, 36, 2499400, 37, 2749300, 38, 3017100, 39, 3303300, 40, 3608200, 41, 3932200, 42, 4272400, 43, 4629200, 44, 5002900, 45, 5393700, 46, 5801900, 47, 6239500, 48, 6707000, 49, 7205000, 50, 7734000, 51, 8598000, 52, 9656400, 53, 10923600, 54, 12478800, 55, 14350800, 56, 16568400, 57, 19160400, 58, 22155600, 59, 25582800, 60, 29470800, 61, 33940800, 62, 38813800, 63, 44129800, 64, 49938800, 65, 56302800, 66, 63297800, 67, 71019800, 68, 79594800, 69, 89187800, 70, 100013800, 71, 112462800, 72, 126343800, 73, 141899800, 74, 159398400, 75, 179148400, 76, 201478400, 77, 226818400, 78, 255468400, 79, 288218400, 80, 325868400];
var message = '!xp 40 60';
var lvls = [parseInt(message.split(' ')[1]), parseInt(message.split(' ')[2])]; // Getting the lvls in question
lvls = lvls.map(l => xparray[xparray.indexOf(l)+1]); // Getting the xp values in question
console.log(lvls[1] - lvls[0]); // Substract xp values
With two-dimensional array (with use of a map to simplify):
Map that two dimensional array to a Map or use a Map in the first place. Then just get the correct xp value by the lvl key.
var xparray = [[1, 0], [2, 300], [3, 900], [4, 2000], [5, 3700]];
var xpMap = new Map(xparray); // Map constructor takes the two dimensional array (key=lvl, value=xp)
var message = '!xp 2 3';
var lvls = [parseInt(message.split(' ')[1]), parseInt(message.split(' ')[2])]; // Getting the lvls in question
lvls = lvls.map(l => xpMap.get(l)); // Just map it by getting the value for the key
console.log(lvls[1] - lvls[0]); // Substract xp values
jsfiddle with all the data which crashes and doesn't run.
jsfiddle with less data which runs but if you
console.log(`row ${g}, col ${i}`);
console.log(obj[pastWinners]);
It shows it is undefined.
I have a multi dimensional array in Javascript which runs some calculations for me. This array gets converted to a object literal and then after some data manipulation is changed to a json object and eventually a string. The program works great!
I have to add 310 more lines to the multi dimensional array. When I do I get this error,
index.html:331 Uncaught TypeError: Cannot read property '0' of
undefined
The original array looks like this,
var pastWinners = [
[2, 9, 19, 23, 38, 40],
[17, 25, 31, 35, 38, 43],
[8, 10, 17, 30, 33, 43],
[10, 17, 26, 28, 36, 43],
[14, 20, 25, 28, 34, 41],
[8, 13, 21, 23, 25, 43],
[10, 11, 18, 24, 27, 30],
[21, 22, 23, 26, 33, 39],
[6, 21, 23, 29, 36, 40],
[10, 12, 16, 21, 25, 42],
[1, 11, 20, 27, 34, 37]
];
Notice the single digit numbers do not have a 0 in the tens place. But the new data looks like this,
[05, 07, 17, 18, 33, 35],
It does have a 0 in the tens place. I mention this because from aside from it being 310 more lines to the array that is the only difference. I have checked the data 50 times and there is nothing wrong with it.
Would a small difference like that make a difference to cause an error like this? It says the error is getting throws at line 331 in my program,
var obj = {};
for (var g = 0; g < pastWinners.length; g++) {
for (var i = 0, j = pastWinners.length; i < j; i++) {
if (obj[pastWinners[g][i]] == undefined) {
console.log(`row ${g}, col ${i}`);
console.log(obj[pastWinners]);
}
if (obj[pastWinners[g][i]]) { //this is line 331
obj[pastWinners[g][i]]++;
} else {
obj[pastWinners[g][i]] = 1;
}
}
}
var picks = [];
for (var numbs in obj) {
picks.push([numbs, obj[numbs]])
picks.sort(
function(a, b) {
return a[1] - b[1]
}
)
}
picks.reverse();
var topPicks = []
for (var winners = 0; winners < 6; winners++) {
topPicks.push(picks[winners][0]);
}
var weekPicks = topPicks.toString();
console.log(weekPicks);
alert(weekPicks);
Does anyone see any reason this would happen when I add this data in? If it is an issue of the size of the array how can I handle this because I have a few thousand more lines of data to add in.
row 0, col 0
index.html:333 undefined
index.html:332 row 0, col 1
index.html:333 undefined
index.html:332 row 0, col 2
index.html:333 undefined
index.html:332 row 0, col 3
index.html:333 undefined
index.html:332 row 0, col 4
index.html:333 undefined
index.html:332 row 0, col 5
index.html:333 undefined
index.html:332 row 0, col 6
index.html:333 undefined
By adding a console.log(g) of what index you were up to when the error happens, this is actually an issue with your data:
[2, 7, 8, 9, 27, 38],
[9, 12, 17, 24, 26, 41]
[18, 20, 21, 31, 40, 44],
You are missing a comma after the 176th index. https://jsfiddle.net/6h7bedtL/1/
Try to print the array in the console when you get undefined and check your array size in the log.
for (var g = 0; g < pastWinners.length; g++) {
for (var i = 0, j = pastWinners.length; i < j; i++) {
if (obj[pastWinners[g][i]] == undefined){
console.log(`row ${g}, col ${i}`);
console.log(obj[pastWinners]);
}
if (obj[pastWinners[g][i]]) { //this is line 331
obj[pastWinners[g][i]]++;
} else {
obj[pastWinners[g][i]] = 1;
}
}
}
I would do it differently:
a. change the second loop...
b. define obj
var pastWinners = [
[2, 9, 19, 23, 38, 40],
[17, 25, 31, 35, 38, 43],
[8, 10, 17, 30, 33, 43],
[10, 17, 26, 28, 36, 43],
[14, 20, 25, 28, 34, 41],
[8, 13, 21, 23, 25, 43],
[10, 11, 18, 24, 27, 30],
[21, 22, 23, 26, 33, 39],
[6, 21, 23, 29, 36, 40],
[10, 12, 16, 21, 25, 42],
[1, 11, 20, 27, 34, 37],
];
var obj=[];
for (var g = 0; g < pastWinners.length; g++) {
for (var i = 0; i < pastWinners[g].length; i++) {
if (obj[pastWinners[g][i]]) { //this is line 331
obj[pastWinners[g][i]]++;
} else {
obj[pastWinners[g][i]] = 1;
}
}
}
console.log(obj)
Also you should check for the existence of pastWinners[g] before you loop through it or try to access a child array using
if (pastWinners[g] != null) {
The reason for this is that if pastWinners[g] for some reason is not defined, then your script will attempt to do this:
undefined[i] or get the value of [i] from undefined -- which it cant because undefined is not an array -- which breaks your script
var pastWinners = [
[2, 9, 19, 23, 38, 40],
[17, 25, 31, 35, 38, 43],
[8, 10, 17, 30, 33, 43],
[10, 17, 26, 28, 36, 43],
[14, 20, 25, 28, 34, 41],
[8, 13, 21, 23, 25, 43],
[10, 11, 18, 24, 27, 30],
[21, 22, 23, 26, 33, 39],
[6, 21, 23, 29, 36, 40],
[10, 12, 16, 21, 25, 42],
[1, 11, 20, 27, 34, 37],
];
for (var g = 0; g < pastWinners.length; g++) {
if (pastWinners[g] != null) { // check for valid item
for (var i = 0, j = pastWinners[g].length; i < j; i++) {
if (pastWinners[g][i] != null) {
pastWinners[g][i]++;
} else {
pastWinners[g][i] = 1;
}
}
}
}
console.log(pastWinners);
Possibly
for (var i = 0, j = pastWinners.length; i < j; i++)
should be
for (var i = 0, j = pastWinners[g].length; i < j; i++)
The array items in pastWinners do not have the length of pastwinners :D