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
Related
This question already has answers here:
How do I loop through or enumerate a JavaScript object?
(48 answers)
Closed 1 year ago.
i have a problem with the code, idk how to optimalize the code to work for every new "person" in object.
customers_data={
'Ben10': [22, 30, 11, 17, 15, 52, 27, 12],
'Sameer': [5, 17, 30, 33, 40, 22, 26, 10, 11, 45],
'Zeeshan': [22, 30, 11, 5, 17, 30, 6, 57]
}
var count = 0
for (let e of customers_data.Ben10) { if (e >= 20) count ++}
if (count >= 5) {console.log("Ben10 has Premium Membership")}
count = 0
for (let e of customers_data.Sameer) { if (e >= 20) count ++}
if (count >= 5) {console.log("Sameer has Premium Membership")}
count = 0
for (let e of customers_data.Zeeshan) { if (e >= 20) count ++}
if (count >= 5) {console.log("Zeeshan has Premium Membership"); count = 0}
count = 0
customers_data={
'Ben10': [22, 30, 11, 17, 15, 52, 27, 12],
'Sameer': [5, 17, 30, 33, 40, 22, 26, 10, 11, 45],
'Zeeshan': [22, 30, 11, 5, 17, 30, 6, 57]
}
var count = 0
for(let prop in customers_data)
{
for (let e of customers_data[prop]) { if (e >= 20) count ++}
if (count >= 5) {console.log(prop + " has Premium Membership")}
count = 0
}
Use two loops. Outer to loop name => values, inner to loop values
let customers_data = {
'Ben10': [22, 30, 11, 17, 15, 52, 27, 12],
'Sameer': [5, 17, 30, 33, 40, 22, 26, 10, 11, 45],
'Zeeshan': [22, 30, 11, 5, 17, 30, 6, 57]
}
for (let dataKey in customers_data) {
let count = 0;
for (let value of customers_data[dataKey]) {
if (value >= 20) {
count++;
}
}
if (count >= 5) {
console.log(dataKey + " has Premium Membership");
}
}
You can DRY this out a little by using a function into which you pass the data, and the name you want to check, and then return a message based on the result.
const customers_data = {
Ben10: [22, 30, 11, 17, 15, 52, 27, 12],
Sameer: [5, 17, 30, 33, 40, 22, 26, 10, 11, 45],
Zeeshan: [22, 30, 11, 5, 17, 30, 6, 57]
}
// Accept data and a name
function hasMembership(data, name) {
// `filter` out the numbers that are greater
// or equal to 20
const greaterThan20 = data[name].filter(entry => {
return entry >= 20;
});
// If the length of the filtered array is
// greater or equal to five, return a positive message
if (greaterThan20.length >= 5) {
return `${name} has Premium Membership!`;
}
// Otherwise return something else
return `Boo. No membership for ${name}.`;
}
console.log(hasMembership(customers_data, 'Ben10'));
console.log(hasMembership(customers_data, 'Sameer'));
console.log(hasMembership(customers_data, 'Zeeshan'));
Additional documentation
filter
Template/string literals
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 am working through freecodecamp's basic algorithm challenges. The challenge is to return the largest number in an array. Here's the code.
function largestOfFour(arr) {
// You can do this!
let largestWord = [0,0,0,0];
for(let i = 0; i < arr.length; i++) {
for(let j = 0; j < arr[i].length; j++) {
if(arr[i][j] > largestWord[i]) {
largestWord[i] = arr[i][j];
}
}
}
return largestWord;
}
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);
I have passed three of the criteria:
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]) should return an array.
Passed
largestOfFour([[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]]) should return [27, 5, 39, 1001].
Passed
largestOfFour([[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]]) should return [9, 35, 97, 1000000].
All except largestOfFour([[17, 23, 25, 12], [25, 7, 34, 48], [4, -10, 18, 21], [-72, -3, -17, -10]]) should return [25, 48, 21, -3].
Where did I go wrong?
So in your code you went wrong in this block.
if(arr[i][j] > largestWord[i]) {
largestWord[i] = arr[i][j];
}
The thing you forgot was you have a starting value for the largest number which is 0 and you compare array elements with that value. Only a value exceeds 0 going to replace that. So I would suggest just to initialize the array without values and do a check for that
//initialize the array without a value
let largestWord = new Array(4);
for(let i = 0; i < arr.length; i++) {
for(let j = 0; j < arr[i].length; j++) {
//also add a check for initial value
if(arr[i][j] > largestWord[i] || largestWord[i] == undefined) {
largestWord[i] = arr[i][j];
}
}
}
Seems you can do this a lot easier with .map() and Math.max()
function largestOfFour(arr) {
return arr.map(x => Math.max(...x));
}
console.log(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]));
console.log(largestOfFour([[17, 23, 25, 12], [25, 7, 34, 48], [4, -10, 18, 21], [-72, -3, -17, -10]]));
I currently have the following array set up:
var TicketInfo =
{
t1: {
1: [7, 12, 35,39,41, 43],
2: [7, 15, 20,34,45, 48],
3: [3, 7, 10, 13, 22, 43],
4: [2, 4, 5,23,27, 33]
},
t2: {
1: [10, 12, 17,44,48, 49],
2: [13, 15, 17, 18, 32, 39],
3: [16, 17, 20, 45, 48, 49],
4: [6, 16, 18, 21, 32, 40]
}
}
What I want to do is iterate through these to bring back the arrays under.
As a test I've tried something like this:
for(t in TicketInfo["t1"])
{
i++;
Write(t.i);
}
But it's obviously not working how I want it to.
Any ideas?
I want to be able to output the arrays like [7, 12, 35,39,41, 43]
Thanks
var TicketInfo =
{
t1: {
1: [7, 12, 35,39,41, 43],
2: [7, 15, 20,34,45, 48],
3: [3, 7, 10, 13, 22, 43],
4: [2, 4, 5,23,27, 33]
},
t2: {
1: [10, 12, 17,44,48, 49],
2: [13, 15, 17, 18, 32, 39],
3: [16, 17, 20, 45, 48, 49],
4: [6, 16, 18, 21, 32, 40]
}
}
for(var j in TicketInfo )
{
for(var p in TicketInfo[j] )
{
for(var i = 0; i < TicketInfo[j][p].length; i++ )
{
console.log(TicketInfo[j][p][i]);
}
}
}
http://jsfiddle.net/J6rTj/
If you're here from google trying to find a way to do a quick print for debugging, here's a one liner for you:
console.log(myArray.join("\n"))
Example:
var myArray = [[1,2,3],[4,5,6],[7,8,9]];
console.log(myArray.join("\n"));
Output:
1,2,3
4,5,6
7,8,9
Example with proper brackets:
var myArray = [[1,2,3],[4,5,6],[7,8,9]];
console.log("[[" + myArray.join("],\n[") + "]]");
Output:
[[1,2,3],
[4,5,6],
[7,8,9]]
Answer to OP's question:
obj = {
1: [7, 12, 35,39,41, 43],
2: [7, 15, 20,34,45, 48],
3: [3, 7, 10, 13, 22, 43],
4: [2, 4, 5,23,27, 33],
}
var keys = Object.keys(obj);
keys.sort();
console.log(keys);
var listFromObj = []
for (var i = 0; i < keys.length; i++) {
if (obj.hasOwnProperty(keys[i])) listFromObj.push(obj[keys[i]]);
}
console.log("[" + listFromObj.join("]\n[") + "]");
Output:
[7,12,35,39,41,43]
[7,15,20,34,45,48]
[3,7,10,13,22,43]
[2,4,5,23,27,33]
The syntax is TicketInfo["t1"]["1"][0].
That example will give you 7.
TicketInfo["t1"]["1"] will give you the array you're after at the base of your question.
In your code t just represents the key.
Try following code:
var TicketInfo =
{
t1: {
1: [7, 12, 35,39,41, 43],
2: [7, 15, 20,34,45, 48],
3: [3, 7, 10, 13, 22, 43],
4: [2, 4, 5,23,27, 33]
},
t2: {
1: [10, 12, 17,44,48, 49],
2: [13, 15, 17, 18, 32, 39],
3: [16, 17, 20, 45, 48, 49],
4: [6, 16, 18, 21, 32, 40]
}
}
for(t in TicketInfo["t1"])
{
i++;
console.log(TicketInfo["t1"][t]);
}
Do I understand that you want to output entire table in order? Since you use objects on t1/t2 level, you'll have to do extra steps for that.
First, see if you can simply replace objects with real arrays:
var TicketInfoArrays = {
t1: [
[7, 12, 35,39,41, 43],
[7, 15, 20,34,45, 48],
[3, 7, 10, 13, 22, 43],
[2, 4, 5,23,27, 33]
]
}
var t1 = TicketInfoArrays.t1
for(var idx = 0, len = t1.length; idx<len; idx++){
var line = idx+": ["
var nested = t1[idx]
for(var idx2 = 0, len2 = nested.length; idx2<len2; idx2++){
line += ((idx2 > 0 ? ', ':'') + nested[idx2])
}
console.log(line + ']')
}
If that's somehow impossible, but you sure that keys in those objects always start at some specific number and go ascending without gaps, you can simply itreate over properties until you hit empty element:
var TicketInfo = {
t1: {
1: [7, 12, 35,39,41, 43],
2: [7, 15, 20,34,45, 48],
3: [3, 7, 10, 13, 22, 43],
4: [2, 4, 5,23,27, 33]
}
}
var t1 = TicketInfo.t1
var idx = 1
var nested
while(nested = t1[idx]){
var line = idx+": ["
var nested = t1[idx]
for(var idx2 = 0, len2 = nested.length; idx2<len2; idx2++){
line += ((idx2 > 0 ? ', ':'') + nested[idx2])
}
console.log(line + ']')
idx++
}
Finally, if you can't guarantee even that, you will have to manually collect all keys, sort them and then iterate over this sorted list.
var TicketInfoUnordered = {
t1: {
8: [7, 12, 35,39,41, 43],
20: [7, 15, 20,34,45, 48],
45: [3, 7, 10, 13, 22, 43],
3: [2, 4, 5,23,27, 33]
}
}
var t1 = TicketInfoUnordered.t1
var keys = []
for(key in t1){
if(t1.hasOwnProperty(key)){ keys.push(key) }
}
keys.sort(function(a, b){ return a - b })
for(var idx = 0, len = keys.length; idx<len; idx++){
var line = keys[idx]+": ["
var nested = t1[keys[idx]]
for(var idx2 = 0, len2 = nested.length; idx2<len2; idx2++){
line += ((idx2 > 0 ? ', ':'') + nested[idx2])
}
console.log(line + ']')
}