Create a stacked percentage column - javascript

I have a collection of data like this :
var data = [
{"p301a":"10","p301b":"7","p301c":"7","p301d":"3","p301e":"8","p301f":"8","p301g":"8","p301h":"8","p301i":"8","p301j":"8","p301k":"8","p301l":"8","p301m":"8","p301n":"8","p301o":"8","age":"31-40 years","profesion":"2","position":"2"},
{"p301a":"5","p301b":"4","p301c":"4","p301d":"4","p301e":"4","p301f":"4","p301g":"4","p301h":"4","p301i":"4","p301j":"4","p301k":"4","p301l":"4","p301m":"4","p301n":"4","p301o":"4","age":"24-30 years","profesion":"2","position":"2"},
{"p301a":"8","p301b":"8","p301c":"3","p301d":"9","p301e":"9","p301f":"4","p301g":"9","p301h":"4","p301i":"2","p301j":"9","p301k":"4","p301l":"9","p301m":"4","p301n":"9","p301o":"9","age":"31-40 years","profesion":"1","position":"3"},
{"p301a":"3","p301b":"3","p301c":"3","p301d":"8","p301e":"9","p301f":"9","p301g":"8","p301h":"9","p301i":"9","p301j":"9","p301k":"8","p301l":"8","p301m":"3","p301n":"3","p301o":"3","age":"31-40 years","profesion":"1","position":"3"},
{"p301a":"6","p301b":"5","p301c":"5","p301d":"8","p301e":"7","p301f":"5","p301g":"6","p301h":"2","p301i":"6","p301j":"5","p301k":"7","p301l":"7","p301m":"4","p301n":"8","p301o":"3","age":"24-30 years","profesion":"1","position":"2"},
{"p301a":"8","p301b":"8","p301c":"4","p301d":"4","p301e":"4","p301f":"5","p301g":"4","p301h":"4","p301i":"4","p301j":"4","p301k":"4","p301l":"9","p301m":"9","p301n":"9","p301o":"4","age":"31-40 years","profesion":"2","position":"3"}
];
From the data I want to create a Stacked percentage column from highchartjs,
With the stipulation of each bar having the number of p301a = 1, p301a = 2 and so on up to 10.
I think it can be done using underscore.js, but I do not know how.
i want to create somthing like this
example
or i want to get data like this :
var xAxis: {
categories: ['a', 'b', 'c' ... 'o' ]
},
var series: [{
name: '1',
data: [5, 3, 4, 7, 2, 5, 9, 5, 8, 4, 5, 7, 8, 3, 4]
}, {
name: '2',
data: [2, 2, 3, 2, 1, 5, 9, 5, 8, 4, 5, 7, 8, 3, 4]
}, {
name: '3',
data: [3, 4, 4, 2, 5, 5, 9, 5, 8, 4, 5, 7, 8, 3, 4]
}, {
name: '4',
data: [3, 4, 4, 2, 5, 5, 9, 5, 8, 4, 5, 7, 8, 3, 4]
}, ... (until 10)]
Sorry for the english
Please help

Related

Divide matrix to sub matrices (Javascript) [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I need this for a codewars challenge to make my code DRY
I have an array of arrays, lets say a 9x9 matrix.
const sudokuTest2= [
[5, 3, 4, 6, 7, 8, 9, 1, 2],
[6, 7, 2, 1, 9, 0, 3, 4, 9],
[1, 0, 0, 3, 4, 2, 5, 6, 0],
[8, 5, 9, 7, 6, 1, 0, 2, 0],
[4, 2, 6, 8, 5, 3, 7, 9, 1],
[7, 1, 3, 9, 2, 4, 8, 5, 6],
[9, 0, 1, 5, 3, 7, 2, 1, 4],
[2, 8, 7, 4, 1, 9, 6, 3, 5],
[3, 0, 0, 4, 8, 1, 1, 7, 9],
];
How can I divide it automatically into 9 equal areas, something which results from the following sample code:
const areas = [];
areas[0] = sudokuTest2[0]
.slice(0, 3)
.concat(sudokuTest2[1].slice(0, 3))
.concat(sudokuTest2[2].slice(0, 3));
areas[1] = sudokuTest2[3]
.slice(0, 3)
.concat(sudokuTest2[4].slice(0, 3))
.concat(sudokuTest2[5].slice(0, 3));
areas[2] = sudokuTest2[6]
.slice(0, 3)
.concat(sudokuTest2[7].slice(0, 3))
.concat(sudokuTest2[8].slice(0, 3));
areas[3] = sudokuTest2[0]
.slice(3, 6)
.concat(sudokuTest2[1].slice(3, 6))
.concat(sudokuTest2[2].slice(3, 6));
areas[4] = sudokuTest2[3]
.slice(3, 6)
.concat(sudokuTest2[4].slice(3, 6))
.concat(sudokuTest2[5].slice(3, 6));
areas[5] = sudokuTest2[6]
.slice(3, 6)
.concat(sudokuTest2[7].slice(3, 6))
.concat(sudokuTest2[8].slice(3, 6));
areas[6] = sudokuTest2[0]
.slice(6, 9)
.concat(sudokuTest2[1].slice(6, 9))
.concat(sudokuTest2[2].slice(6, 9));
areas[7] = sudokuTest2[3]
.slice(6, 9)
.concat(sudokuTest2[4].slice(6, 9))
.concat(sudokuTest2[5].slice(6, 9));
areas[8] = sudokuTest2[6]
.slice(6, 9)
.concat(sudokuTest2[7].slice(6, 9))
.concat(sudokuTest2[8].slice(6, 9));
For sure I could use some nested loops, but I'm curious if there is any solution with array methods.
What will be the best solution, what do you think?
You could take generate the wanted 3x3 parts by using a nested mapping.
const
sudoku = [[5, 3, 4, 6, 7, 8, 9, 1, 2], [6, 7, 2, 1, 9, 0, 3, 4, 9], [1, 0, 0, 3, 4, 2, 5, 6, 0], [8, 5, 9, 7, 6, 1, 0, 2, 0], [4, 2, 6, 8, 5, 3, 7, 9, 1], [7, 1, 3, 9, 2, 4, 8, 5, 6], [9, 0, 1, 5, 3, 7, 2, 1, 4], [2, 8, 7, 4, 1, 9, 6, 3, 5], [3, 0, 0, 4, 8, 1, 1, 7, 9]],
areas = Array
.from({ length: 3 })
.flatMap((_, i) => Array
.from(
{ length: 3 },
(__, j) => Array
.from({ length: 3 })
.flatMap((___, k) => sudoku[j * 3 + k].slice(i * 3, (i + 1) * 3)
)
));
areas.forEach(a => console.log(...a));
This can be done in with single forEach method. The idea behind this is dynamic indexing.
const matrix = [ [5, 3, 4, 6, 7, 8, 9, 1, 2], [6, 7, 2, 1, 9, 0, 3, 4, 9], [1, 0, 0, 3, 4, 2, 5, 6, 0], [8, 5, 9, 7, 6, 1, 0, 2, 0], [4, 2, 6, 8, 5, 3, 7, 9, 1], [7, 1, 3, 9, 2, 4, 8, 5, 6], [9, 0, 1, 5, 3, 7, 2, 1, 4], [2, 8, 7, 4, 1, 9, 6, 3, 5], [3, 0, 0, 4, 8, 1, 1, 7, 9],];
let areas = new Array(9).fill([]);
matrix.forEach((numbers, idx)=> {
let segment = Math.floor(idx / 3);
areas[segment] = [...areas[segment], ...matrix[idx].slice(0, 3)];
areas[segment + 3] = [...areas[segment + 3], ...matrix[idx].slice(3, 6)];
areas[segment + 6] = [...areas[segment + 6], ...matrix[idx].slice(6, 9)];
})
areas.forEach(area => console.log(...area));

Passing an array to a function parameter and getting values from nested array

I got stuck while practicing credit card checker practice.
My code:
// All valid credit card numbers
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8]
const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9]
const valid3 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6]
const valid4 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5]
const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6]
// All invalid credit card numbers
const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5]
const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3]
const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4]
const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5]
const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4]
// Can be either valid or invalid
const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4]
const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9]
const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3]
const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3]
const mystery5 = [4, 9, 1, 3, 5, 4, 0, 4, 6, 3, 0, 7, 2, 5, 2, 3]
// An array of all the arrays above
const batch = [valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5]
// Add your functions below:
const validateCred = (array)=> {
let tempArrSub = []; //Holds values of the 9 subtracted from doubled elements bigger than 9
let tempArr = array; //Copies the values of the array passed into parameters
tempArr.pop();
tempArr.reverse();
for (let i = tempArr.length-1; i >=0; i-=2){ //Doubles every two elements from right to left
tempArr[i] *= 2;
}
for (let k = 0; k < tempArr.length; k++) { //Subtract 9 from every second element (right to left) if bigger than 9
if (tempArr[k] > 9){
tempArrSub.push(tempArr[k] - 9);
}
else {
tempArrSub.push(tempArr[k]);
}
}
let tempArrSum = 0;
for (let m = 0; m < tempArrSub.length; m++){ //Calculates the sum of all elements in the array
tempArrSum += tempArrSub[m];
}
tempArrSum += array.pop(); //Adds the last digit of initial array to the sum
if (tempArrSum % 10 === 0) { //Returns true if the sum is divisible by 10
return true;
}
else {
return false;
}
} //End Of Function
const findInvalidCards = (nestedArray) => {
let invalidCards = [];
let validCards = [];
for (let a = 0; a < nestedArray.length; a++){
if ( validateCred(nestedArray[a]) == true ) {
validCards.push(nestedArray[a]);
}
else {
invalidCards.push(nestedArray[a]);
}
}
console.log("Invalid cards: \n" + invalidCards);
console.log("Valid cards: \n" + validCards);
}
I checked all arrays one by one passing as an argument to validateCred() function. It's working and returning true or false for each credit card.
In order to automate process I wanted findInvalidCards() to find valid or invalid cards by calling validateCred() function inside itself and returning boolean value for each card.
Here I got stuck. Because it is returning true for the 1st card and false for the remaining cards. I've been playing with the code for the whole day, but I could not move forward. I rely on your help. Thanks in advance
I don't know if is it helpful to you or not. But I rewrite your code with an optimal way.
// All valid credit card numbers
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8]
const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9]
const valid3 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6]
const valid4 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5]
const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6]
// All invalid credit card numbers
const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5]
const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3]
const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4]
const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5]
const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4]
// Can be either valid or invalid
const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4]
const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9]
const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3]
const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3]
const mystery5 = [4, 9, 1, 3, 5, 4, 0, 4, 6, 3, 0, 7, 2, 5, 2, 3]
// An array of all the arrays above
const batch = [valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5];
isValidCard = (array) => {
let copy = [...array];
const last = copy.pop();
copy.reverse();
copy = copy.map((dig, i) => ((i % 2 === 0 ? dig * 2 : dig)));
copy = copy.map(dig => (dig > 9 ? dig - 9 : dig));
const sum = copy.reduce((acc, curr) => acc + curr);
return ((sum + last) % 10 === 0);
}
findInvalidCards = (array) => {
const validList = [];
const invalidList = [];
array.forEach(card => {
if (isValidCard(card)) {
validList.push(card);
} else {
invalidList.push(card);
}
});
console.log('valid cards', validList);
console.log('invalid cards', invalidList);
}
findInvalidCards(batch);
I think your issue is this line:
let tempArr = array; //Copies the values of the array passed into parameters
According to your comment you want to copy the array, but just assigning it to another variable does not copies it. In order to copy just so something like this:
let copy = array.slice(0);
/* or (will not work for large arrays) */
let copy = [...array];
// All valid credit card numbers
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9];
const valid3 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6];
const valid4 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5];
const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6];
// All invalid credit card numbers
const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5];
const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3];
const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4];
const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5];
const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4];
const invalidCredit = [invalid1, invalid2, invalid3, invalid4, invalid5]
// Can be either valid or invalid
const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4];
const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9];
const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3];
const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3];
const mystery5 = [4, 9, 1, 3, 5, 4, 0, 4, 6, 3, 0, 7, 2, 5, 2, 3];
// An array of all the arrays above
const batch = [valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5];
// Add your functions below:
const validateCred = (arr) => {
let reversedArr = arr.reverse();
let oddOccurrences = [];
reversedArr.forEach((value, i) => i % 2 ? oddOccurrences.push(value *= 2) : oddOccurrences.push(value));
const checking = oddOccurrences.map((greater) => (greater > 9 ? (greater -= 9) : greater));
const sum = checking.reduce((acc, num) => {
return acc + num
}, 0)
// Conditional check
if (sum % 10 === 0)
return 'valid'
else return 'invalid'
}
console.log(validateCred([4, 5, 3, 9, 6, 8, 9, 8, 8, 7, 7, 0, 5, 7, 9, 8]));
findInvalidCards = (newArr) => {
const invalidList = [];
const validList = [];
for (let i = 0; i < newArr.length; i += 15) {
// inner loop
for (let j = 0; j < newArr.length; j++) {
validateCred(newArr[j]) === 'invalid' ? invalidList.push(newArr[j]) : validList.push(newArr[j]);
}
};
console.log(invalidList)
}
findInvalidCards(batch);

how to concat two object arrays of different size by key using lodash

Stocks: [{
PRN: 1,
PID: 1,
Qty: 3,
SlNos: [1, 2, 3]
}, {
PRN: 1,
PID: 2,
Qty: 4,
SlNos: [10, 11, 12, 13]
}, {
PRN: 2,
PID: 1,
Qty: 3,
SlNos: [4, 5, 6]
}, {
PRN: 2,
PID: 2,
Qty: 4,
SlNos: [14, 15, 16, 17]
}]
I want this array as bellow with Lodash
Stocks: [{
PID: 1,
Qty: 6,
SlNos: [1, 2, 3, 4, 5, 6]
}, {
PID: 2,
Qty: 4,
SlNos: [10, 11, 12, 13, 14, 15, 16, 17]
}]
Here is a solution with _lodash:
var stocks = [{ PRN: 1, PID: 1, Qty: 3, SlNos: [1, 2, 3] }, { PRN: 1, PID: 2, Qty: 4, SlNos: [10, 11, 12, 13] }, { PRN: 2, PID: 1, Qty: 3, SlNos: [4, 5, 6] }, { PRN: 2, PID: 2, Qty: 4, SlNos: [14, 15, 16, 17] }]
const result = _.reduce(stocks, (r, {PRN, ...c}) => {
let _c = _.find(r, {'PID': c.PID})
if(_c)
_c = _.mergeWith(_c, c, (ov, sv, k) => _.includes(['Qty','SlNos'], k) ? _.isArray(sv) ? (ov || []).concat(sv) : _.isNumber(sv) ? sv + (ov || 0) : sv : ov)
else
r.push(c)
return r
}, [])
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
We are using reduce with mergeWith (which is the main thing here really) plus a little bit of includes.
Here is a solution without lodash that will do the trick:
var stocks = [{ PRN: 1, PID: 1, Qty: 3, SlNos: [1, 2, 3] }, { PRN: 1, PID: 2, Qty: 4, SlNos: [10, 11, 12, 13] }, { PRN: 2, PID: 1, Qty: 3, SlNos: [4, 5, 6] }, { PRN: 2, PID: 2, Qty: 4, SlNos: [14, 15, 16, 17] }]
const result = stocks.reduce((r, c) => {
_c = r.find(x => x.PID === c.PID)
if (_c) {
_c.PID = c.PID
_c.Qty = _c.Qty + c.Qty
_c.SlNos = _c.SlNos ? _c.SlNos.concat(c.SlNos) : c.SlNos
} else {
r.push(!delete(c.PRN) || c)
}
return r
}, [])
console.log(result)
The idea is to use reduce and first find if we had already that object by PID if so sum the values if not insert to the final array. Since we are going through each record that logic does the trick in one loop.

Iterating over an object of arrays and calculating average

I have the following data structure and need to get an average value for each of the columns for the items in the contenders object. I then need to turn this into an array of arrays. The first value needs to be the columns average (rounded) the second needs to be an incremented value starting at 0. e.g.
output = [[6, 0], [4, 1], [3, 2], [3, 3], [6, 4]];
Example structure:
input = {
categories: [
"Cat 1",
"Cat 2",
"Cat 3",
"Cat 4",
"Cat 5"
],
contenders: {
item1: [5, 3, 4, 4, 6],
item2: [6, 10, 4, 4, 6],
item3: [6, 3, 4, 9, 6],
item4: [8, 3, 5, 4, 6],
item5: [9, 3, 4, 4, 6],
item6: [10, 2, 7, 4, 6],
item7: [4, 3, 4, 4, 6],
item8: [1, 5, 4, 4, 6]
},
misc: [0, 3, 4, 4, 6]
};
I've created a function that can do the average for me:
function getAvg(data) {
return data.reduce(function (p, c) {
return p + c;
}) / data.length;
}
But can't quite work out how to iterate over the values for the items to get my result.
If I understood correctly and you want an average of each column, which would mean each first element in all the arrays in your items keys as example, then you would need to make an array of each column to use your average function. However, in doing so you can already calculate the average, here is a way:
var input = { categories: ["Cat 1", "Cat 2", "Cat 3", "Cat 4", "Cat 5"], contenders: { item1: [5, 3, 4, 4, 6], item2: [6, 10, 4, 4, 6], item3: [6, 3, 4, 9, 6], item4: [8, 3, 5, 4, 6], item5: [9, 3, 4, 4, 6], item6: [10, 2, 7, 4, 6], item7: [4, 3, 4, 4, 6], item8: [1, 5, 4, 4, 6] }, misc: [0, 3, 4, 4, 6] }
var output = []
var cols = input.contenders.item1.length // amount of columns (I assume all items have same amount of columns)
for(var i=0;i<cols;i++){
output[i] = [0,i] // start output with sum of 0 and index i
}
for(var key in input.contenders){
var arr = input.contenders[key]
for(var k = 0;k<cols;k++){
output[k][0]+=arr[k] // add the value of the array in the kth position to the kth output sum
}
}
for(var i=0;i<cols;i++){
output[i][0] = Math.round(output[i][0]/Object.keys(input.contenders).length) // now just divide by the amount of keys
}
console.log(output)
You could use a combination of Object.keys to get each item in the contenders, then use map to create a new array from the results:
function getAvg(data) {
return data.reduce(function (p, c) {
return p + c;
}) / data.length;
}
var input = {
categories: [
"Cat 1",
"Cat 2",
"Cat 3",
"Cat 4",
"Cat 5"
],
contenders: {
item1: [5, 3, 4, 4, 6],
item2: [6, 10, 4, 4, 6],
item3: [6, 3, 4, 9, 6],
item4: [8, 3, 5, 4, 6],
item5: [9, 3, 4, 4, 6],
item6: [10, 2, 7, 4, 6],
item7: [4, 3, 4, 4, 6],
item8: [1, 5, 4, 4, 6]
},
misc: [0, 3, 4, 4, 6]
};
console.log(Object.keys(input.contenders).map(function(key, index) {
return [getAvg(input.contenders[key]), index];
}));
You can use Object.keys, for getting the properties and then interate over the values with Array.prototype.forEach.
var input = { categories: ["Cat 1", "Cat 2", "Cat 3", "Cat 4", "Cat 5"], contenders: { item1: [5, 3, 4, 4, 6], item2: [6, 10, 4, 4, 6], item3: [6, 3, 4, 9, 6], item4: [8, 3, 5, 4, 6], item5: [9, 3, 4, 4, 6], item6: [10, 2, 7, 4, 6], item7: [4, 3, 4, 4, 6], item8: [1, 5, 4, 4, 6] }, misc: [0, 3, 4, 4, 6] },
output = [],
sum = [], count = [];
Object.keys(input.contenders).forEach(function (k) {
input.contenders[k].forEach(function (a, i) {
sum[i] = (sum[i] || 0) + a;
count[i] = (count[i] || 0) + 1;
});
});
output = sum.map(function (a, i) {
return [Math.round(sum[i] / count[i]), i]
});
document.write('<pre>' + JSON.stringify(output, 0, 4) + '</pre>');
You should totally go with Object.keys as suggested in other answers. However, for completeness or the unlikely case that compatibility gives you trouble:
You can build a string to refer to the arrays you're looking for, like so
for (var i=1;i<9;i++) { doSomething(input.contenders["item"+i]); }
This would require you to know the number of items and their names in advance.

Add specific values of multidimensional array together Javascript

Okay, so I have a multidimensional array that itself contains 9 arrays. Each of these nested arrays contains 10 numeric values. For sake of simplicity, let's say it all looks like this:
var MyArray = [
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10]
]
I am trying to write a function that will take the first index of each nested array (in this case, all 1's) and add them together, pushing this value either to an array or an object. Then, I need this function to continue on, adding all the values of the next index, and the next, and so on and so forth. In the end, I should have an array of 10 values (or an object works here as well). The values would be:
1+1+1+1+1+1+1+1+1,
2+2+2+2+2+2+2+2+2,
3+3+3+3+3+3+3+3+3...
...and so on so forth, so that the actual values of the new array would be this:
[9, 18, 27, 36, 45, 54, 63, 72, 81]
The catch here is that I need this to by flexible/dynamic, so that it will work in case MyArray has only 6 arrays, or maybe the nested arrays have only 4 values each. It should work with any amount of nested arrays, each with their own amount of values (though each nested array will contain the SAME amount of values as one another!).
What would be the best way to accomplish this via JavaScript and/or jQuery? Note that I could also have the values output to an object, in this fashion:
{1:9, 2:18, 3:27, 4:36, 5:45, 6:54, 7:63, 8:72, 9:81}
I tried using similar code to this from another StackOverflow thread to get an object, but it is returning
{1:NaN, 2:NaN, 3:NaN, etc.}
That thread can be found here:
Javascript Multidimensional Array: Add Values
I'm using the "underscore" method and the jQuery $.each part of it provided by Otto.
Anyone able to help here??
Something like this
var myData = [
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
];
var summed = [];
myData[0].forEach(function (arr, index) {
var sum = myData.reduce(function (a, b) {
return a + b[index];
}, 0);
summed.push(sum);
});
console.log(summed);
On jsfiddle
Here is another solution:
var MyArray = [
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10]
]
var results= [];
MyArray.map(function(a){
for(var i=0;i<a.length;i++){
if(results.length === a.length){
results[i] = results[i] + a[i];
}else{
results.push(a[i]);
}
}
});
http://jsfiddle.net/uMPAA/
A simple array solution would be the following :
var results= [];
for (var i=0;i<MyArray.length;i++) {
for(var j=0; j<MyArray[i].length; j++) {
if(results[j] == undefined) { results[j] = 0; }
results[j] = results[j]+data[i][j];
}
}
Note the if(results[j]==undefined) line -- this is probably what you didn't do. If you omit that, you get NaN on all lines, since you're adding an undefined value to a number.
Another approach to sum columns in multi-dimensional arrays (based on Lodash 4).
var arrays = [
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
];
function sum_col(arrays) {
return _.map(_.unzip(arrays), _.sum);
}
console.log(sum_col(arrays));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

Categories

Resources