Below is the structure of my data;
{
"questions": ["Large choice of food", "Food quality", "Food freshness"],
"countries": ["Netherlands", "Belgium", "France"],
"values": [
[
[5, 88, 18],
[50, 83, 10],
[29, 78, 80]
],
[
[46, 51, 61],
[95, 21, 15],
[49, 86, 43]
],
[
[7, 46, 92],
[54, 94, 31],
[89, 96, 11]
]
]
}
Here is my script for sorting it;
function calculateTotals() {
var countryS = "France"
var country = data.countries.indexOf(countryS);
var values
for (var question= 0; question < data.questions.length; question++) {
// get the values for the question/country
values = data.values[question][country];
console.log(values)
Currently, this outputs this to the console;
So, currently this script is logging the values for each question indexed by country.
I would like to add together each item in this array. So, from this output I would like to do the following additions;
29 + 49 + 89,
78 + 86 + 96,
80 + 43 + 11
I'm not sure how I can do this?
I thought that perhaps using .pop()/.shift() 3 times might work, or just using [0],[1],[2]. However, after returning a single item in the array, I'm not sure how to add the 3 arrays numbers together?
Hope everything is clear, any help/advice is much appreciate!
Plunk Here
You could use an array for the sum amd iterate over the items as well.
Basically this proposal uses Array#forEach.
The forEach() method executes a provided function once per array element.
function calculateTotals() {
var countryS = "France",
country = data.countries.indexOf(countryS),
sum = [];
data.values.forEach(function (question) {
question[country].forEach(function (a, i) {
sum[i] = (sum[i] || 0) + a;
});
});
console.log(sum);
}
var data = { "questions": ["Large choice of food", "Food quality", "Food freshness"], "countries": ["Netherlands", "Belgium", "France"], "values": [[[5, 88, 18], [50, 83, 10], [29, 78, 80]], [[46, 51, 61], [95, 21, 15], [49, 86, 43]], [[7, 46, 92], [54, 94, 31], [89, 96, 11]]] };
calculateTotals();
You can use array map function to iterate over them and perform such an operation.
E.g.
var arr = [[29,49,89], [78,86,96], [80,43,11]];
var final = arr.map(function(v){
var res = 0;
v.forEach(function(e){
res += e;
});
return res;
});
console.log(final); //[167, 260, 134]
For simpler, but not recommended, you can also achieve it by doing,
var arr = [[29,49,89], [78,86,96], [80,43,11]];
var final = arr.map(function(v){
return eval(v.join('+'));
});
console.log(final); //[167, 260, 134]
try the updated plunkr
Here is the updated method
function calculateTotals()
{
var countryS = "France"
var country = data.countries.indexOf(countryS);
var sum = [0,0,0];
for (var question= 0; question < data.questions.length; question++)
{
var values = data.values[question][country];
for( var counter = 0; counter < values.length; counter++ )
{
sum[counter] += values[counter];
}
}
document.body.innerHTML += sum;
}
DEMO
var data = {
"questions": ["Large choice of food", "Food quality", "Food freshness"],
"countries": ["Netherlands", "Belgium", "France"],
"values": [
[
[5, 88, 18],
[50, 83, 10],
[29, 78, 80]
],
[
[46, 51, 61],
[95, 21, 15],
[49, 86, 43]
],
[
[7, 46, 92],
[54, 94, 31],
[89, 96, 11]
]
]
}
function calculateTotals() {
var countryS = "France"
var country = data.countries.indexOf(countryS);
var sum = [0, 0, 0];
for (var question = 0; question < data.questions.length; question++) {
var values = data.values[question][country];
for (var counter = 0; counter < values.length; counter++) {
sum[counter] += values[counter];
}
}
document.body.innerHTML += sum;
}
calculateTotals();
You can use array.reduce to achieve the desired output.
for (var question= 0; question < data.questions.length; question++) {
// get the values for the organization/country
values = data.values[question][country];
console.log(values);
var sumOfValues = values.reduce(
function(previousVal, currentVal) {
return previousVal + currentVal;
}, 0);
console.log("Sum of values");
console.log(sumOfValues);
}
here's the plunkr
https://plnkr.co//TckVhx52VcMGgb0eZjzW?p=preview
EDIT:
array.reduce is one of the fastest methods available. Many links can be found for the info.
I've got one here. See the answers.
How to find the sum of an array of numbers
Try the following with pure JavaScript with nested loops::
(If you want to get all the additions)
var arr = [[29,49,89], [78,86,96], [80,43,11]];
var resultArr;
for(var i = 0, len = arr.length; i < len; i++) {
for(var j = 0, len2 = arr.length; j < len2; j++) {
resultArr+= arr[j][i];
}
}
If you only want to get one sum at a time:
var result;
for(var i = 0, len = arr.length; i < len; i++) {
result+= arr[j]["YourIndex"];
}
Related
I have an array:
var myArray = [12, 11, 13, 18, 30, 51, 21, 18, 20];
I need to remove each 3rd item from the array and add it to another array.
The final result should be:
var myArray = [12, 11 18, 30, 21, 18];
var secondArray = [13, 51, 20];
How can i do that?
iterate over the array and splice every 3rd element and push to the second array.
var myArray = [12, 11, 13, 18, 30, 51, 21, 18, 20];
var secondArray = [];
for (var i = 2; i < myArray.length; i += 2) {
secondArray.push(myArray[i]);
myArray.splice(i, 1);
}
console.info('myArray', myArray)
console.info('secondArray', secondArray)
I do not like example with splicing source array, because splicing is a long operation and in large arrays / multiple operations it will be not so effective. I think you should create new arrays and don't mind.
const arraysList = myArray.reduce((acc, item, index) => {
if ((index + 1) % 3 === 0) {
acc.second.push(item);
} else {
acc.first.push(item);
}
return acc;
}, { first: [], second: [] })
console.log(arraysList.first); // [12, 11 18, 30, 21, 18]
console.log(arraysList.second); // [13, 51, 20]
var myArray = [12, 11, 13, 18, 30, 51, 21, 18, 20];
var newArray1 = [];
var newArray2 = [];
myArray.forEach(function(value,index){
if((index + 1) % 3 === 0){
newArray1.push(value);
}
else {
newArray2.push(value);
}
});
console.log(newArray1); // Stores element at index 3 in the original array
console.log(newArray2); // Stores element at index other than 3 in the original array
Array#reduce the original array into 2 new arrays:
const myArray = [12, 11, 13, 18, 30, 51, 21, 18, 20];
const [without3rdItems, with3rdItems] = myArray.reduce((arrs, n, i) => {
const arr = (i + 1) % 3 ? 0 : 1;
arrs[arr].push(n);
return arrs;
}, [[], []]);
console.log(without3rdItems.join());
console.log(with3rdItems.join());
var a = [12, 11, 13, 18, 30, 51, 21, 18, 20];
var b = [ ];
var l = a.length;
for(i = 2; i < l; i += 2){
b.push(a[i]);
a.splice(i, 1);
l--;
}
console.log("Array a: ", a);
console.log("Array b: ", b);
Not sure what is wrong here but I am trying to add a set of numbers in an array (not the whole array) but it looks like it is summing up the whole array:
function sumPrimes(num) {
var arr = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97];
var total = 0;
var index;
//loop through the whole array
for (var i = 0; i < arr.length; i++) {
//find matching prime number
if (num < arr[i]) {
// get index of prime number in the array
index = arr.indexOf(arr[i]);
//sum up total of prime numbers up to 'num'
for (var b = 0; b < index; b++) {
total = total + arr[index];
}
}
}
return total;
}
sumPrimes(10);
If your goal is to calculate the sum of all prime numbers less than the given number, then the solution is much easier.
Either
function sumPrimes(num) {
var arr = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97];
var total = 0;
for (var x of arr) {
if (x < num)
total += x;
else
break;
}
return total;
}
which works when arr is sorted, or
function sumPrimes(num) {
var arr = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97];
var total = 0;
arr.forEach(function(x) {
if (x < num)
total += x;
}, this);
return total;
}
that would work for an unsorted array as well.
You need to replace index with b:
//sum up total of prime numbers up to 'num'
for(var b=0; b<index; b++){
total = total + arr[b];
}
EDIT: and get rid of the outer loop
Using a complex array (for the use case of tabular data displayed in columns and rows) lets say I have some values:
var values = [
[234, 386, 21, 38],
[-23, 58, 106, 0],
[45, -48, 506, 23],
[109, 168, 42, 111]
];
What would be the best way to return a matching array that would rank the values against their column in the correct (maintained) order? The ranked order would be highest to lowest in this case.
For example, an end result array of:
[
[1, 1, 4, 2],
[4, 3, 2, 4],
[3, 4, 1, 3],
[2, 2, 3, 1]
];
Note how the result is sorted vertically by column.
I would want to use this with a large data set, so any guidance/tips for quickest performance is my aim here.
--
For context: My first attempt was to map the original array with the index values, but I was unsure where to go from there:
var singleColumn = [234, -23, 45, 109];
for (var i = 0; i < singleColumn.length; i++) {
singleColumn[i] = [singleColumn[i], i];
}
Essentially the trick will be retaining original indices after the sort. I've iterated them into a data structure first, sorted it, and then rebuilt the 2-dimensional array structure from the result.
I haven't done any checking to ensure that the input is all well-formed, the assumption is all rows are the same width as the first row.
An optimization that could probably be done would be transforming the raw values into the data-structure during the sort, which would eliminate a pass of the array. I don't see an easy way to do that without losing some of the conciseness and readability, and it would be a pretty small gain.
var values = [
[234, 386, 21, 38],
[-23, 58, 106, 0],
[45, -48, 506, 23],
[109, 168, 42, 111]
];
function buildRanking(arr) {
var result = [];
for(var col = 0; col < arr[0].length; col++) {
//everything inside this for loop is per column
//first use map function to turn the column into an array of objects
//each holding the value and the current index. [{value: 234, index: 1}, etc..]
var sortableStructure = values.map(function(val, i) {
return { value : val[col], index : i };
});
//Sort function to sort my sortableStructure in place on the values
sortableStructure.sort(function(a, b) {
return b.value - a.value;
});
//now iterate over the sortable strucutre
for(var i = 0; i < sortableStructure.length; i++) {
//this ugly bit just makes sure arrays are initialized for each row as needed
if(typeof result[sortableStructure[i].index] === 'undefined')
result[sortableStructure[i].index] = [];
//for the current item in the sortableStructure, get the index
//access the result element corresponding to that index
//(the original position of this sorted value) and push in
//the current index (sort order) + 1 (to switch from zero-based to one-based)
result[sortableStructure[i].index].push(i + 1);
}
}
return result;
}
//To provide visible output.
document.write(JSON.stringify(buildRanking(values)).split('],[').join('],<br/>['));
First pass at this and highly unoptimized but here's a loose implementation where I do it step by step.
function sort(rows) {
var columns = [];
/* Invert rows and columns */
for (var i = 0, row; i < rows.length; i++) {
row = rows[i];
for (var j = 0, col; j < row.length; j++) {
col = rows[i][j];
columns[j] = columns[j] || [];
columns[j][i] = col;
}
}
/* Sort by descending order, returning index */
var sortedColumns = columns.slice(0).map(function(column, i) {
return column.slice(0).sort(function(a, b) {
return b - a;
}).map(function(value, j, sortedColumn) {
return sortedColumn.indexOf(column[j]) + 1;
});
});
/* Invert rows and columns back again */
var sortedRows = [];
for (var i = 0, row; i < sortedColumns.length; i++) {
row = sortedColumns[i];
for (var j = 0, col; j < row.length; j++) {
col = sortedColumns[i][j];
sortedRows[j] = sortedRows[j] || [];
sortedRows[j][i] = col;
}
}
return sortedRows;
}
var values = [
[234, 386, 21, 38],
[-23, 58, 106, 0],
[45, -48, 506, 23],
[109, 168, 42, 111]
];
var expected = [
[1, 1, 4, 2],
[4, 3, 2, 4],
[3, 4, 1, 3],
[2, 2, 3, 1]
];
var sorted = sort(values);
console.log(sorted.toString() === expected.toString()); // true
JSFiddle demo: https://jsfiddle.net/7ek6pz63/2/
Assuming the columns habe to be sorted descending and the result is based on one, then this should work.
var values = [
[234, 386, 21, 38],
[-23, 58, 106, 0],
[45, -48, 506, 23],
[109, 168, 42, 111]
];
function getX(array) {
var length = array[0].length,
result = Array.apply(null, { length: array.length }).map(function () { return []; }),
temp, i;
for (i = 0; i < length; i++) {
temp = [];
array.forEach(function (a, j) {
temp.push({ v: a[i], i: j });
});
temp.sort(function (a, b) {
return b.v - a.v;
}).forEach(function (a, j) {
result[a.i][i] = j + 1;
});
}
return result;
}
document.write('<pre>' + JSON.stringify(getX(values), 0, 4) + '</pre>');
I'm trying to find the maximum values of a multidimensional array.
Input:
[[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]
Result:
[5, 27, 39, 1001]
What I've tried:
var largestArr = [];
function largestOfFour(arr) {
for (var i = 0; i < arr.length; i++) {
var largest = 0;
var currentArr = arr[i];
var stop = currentArr.length;
for (var j = 0; j < stop; j++) {
if (currentArr[0] > largest) {
largest = currentArr[0];
largestArr.push(largest);
largestArr.shift();
}
}
return largestArr;
}
}
largestOfFour([
[4, 5, 1, 3],
[13, 27, 18, 26],
[32, 35, 37, 39],
[1000, 1001, 857, 1]
]);
Can anyone help me understand why this isn't working?
The problem is here
if (currentArr[0]>largest){
largest = currentArr[0];
//
}
This should be done like below:
if (currentArr[j]>largest){
largest = currentArr[j];
//
}
Why this is wrong?
This is wrong because you always compare the first item of each array with the largest and not all the items in each array one after the other.
Furthermore, you have to make a few more corrections.
Specifficaly, there isn't any need to use the shift method. You have only to push the largest value of each array after the end of each processing in the largestArr. Last, but not least you have to move the return statement of the largestArr out of the for loops.
var largestArr = [];
function largestOfFour(arr) {
for (var i=0; i<arr.length; i++) {
var largest = 0;
var currentArr = arr[i];
var stop = currentArr.length;
for (var j=0; j<stop; j++){
if (currentArr[j]>largest){
largest = currentArr[j];
}
}
largestArr.push(largest);
}
return largestArr;
}
alert(largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]));
Since the answer has been provided here's some code can do the same job in a smaller number of lines that you might find useful in the future using reduce.
var out = arr.reduce(function (p, c) {
return p.concat(Math.max.apply(null, c));
}, []);
DEMO
Christos' answer is correct and should the selected as answer.
Additionally though, you should not pollute the global namespace by declaring largestArray outside of the function, considering that you are returning said array anyway.
function largestOfFour(arr) {
var largestArr = []; // put this line here instead of making it global
for (var i=0; i<arr.length; i++) {
var largest = 0;
var currentArr = arr[i];
var stop = currentArr.length;
for (var j=0; j<stop; j++){
if (currentArr[j]>largest){
largest = currentArr[0];
}
}
largestArr.push(largest);
}
return largestArr;
}
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);
Here is my current code:
var largestNumbers = new Array(4);
function largestOfFour(arr) {
var biggest = Math.max.apply(null, largestOfFour)
for (var index in arr) {
for(var i=0; i < arr[index].length; i++){
if (arr[index] > biggest){
arr[index].push(largestNumbers);
}
else if (arr[index] < biggest) {
arr[index].splice(0, 1);
}
}
}
return largestNumbers;
}
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);
My objective is to find the largest number in each of the subarrays and then put those values into another array and then return that value. I have been searching around for things like "How to extract a subarray from array" and that has led to me using the splice function. I'm not sure if I'm using it right, but I'm trying everything I've got because I've been stuck on this problem for 2 days now. If anyone could just lead me in the path to solve this problem, I would be more than grateful. Thank you all so much.
Furthermore, I was using this site to try and guide me along. There is a snippet of code that attempts to resolve a problem similar to mine in the latter half of the page. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
var largest = function largest(arr) {
return arr.map(function(arr) {
return Math.max.apply(null, arr);
});
};
Working example
Use map to create a new Array by looping over the first level.
Use Math.max to get the maximum value from a list of numbers
Use apply to convert the array to arguments in Math.max
function largestOfFour(arr) {
return arr.map(function(array) {
return Math.max.apply(Math, array)
});
}
var myArray = [
[4, 5, 1, 3],
[13, 27, 18, 26],
[32, 35, 37, 39],
[1000, 1001, 857, 1]
];
console.log(largestOfFour(myArray));
Applying simple nested loop's logic.
function largestOfFour(arr) {
var maxArray = [];
for(var i = 0; i < arr.length; i++) {
var maxE = 0;
for(var j = 0; j < arr.length; j++) {
if(maxE < arr[i][j]) {
maxE = arr[i][j];
}
}
maxArray.push(maxE);
}
arr = maxArray;
return arr;
}
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);
OR Try this
function largestOfFour(arr) {
var maxArray = [];
for(var i = 0; i < arr.length; i++) {
var maxE = Math.max(...arr[i]); // this spread is only available in ES6 so can be replaced by --> Math.max.apply(null, arr[i])
maxArray.push(maxE);
}
arr = maxArray;
return arr;
}
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);
Just do it with a simple nested loop. Find the biggest number for each inner array and add it to the result:
function largestOfFour(arr) {
var result = [];
for(var i = 0; i < arr.length; i++){
var max = 0;
var inner = arr[i];
for(var j = 0; j < inner.length; j++){
if(inner[j] > max)
max = inner[j];
}
result.push(max);
}
return result;
}
var output = largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);
// [5, 27, 39, 1001]
Here is a working example
function largestOfFour(arr) {
return arr.reduce(function(p, c, index, arr){
p.push(Math.max.apply(null, c));
return p;
}, []);
}
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);
Even you can code like this also , creating a new array showing in them also
function largestOfFour(arr) {
// You can do this!
var newArray=[];
for(i=0;i<arr.length;i++){
newArray.push(Math.max.apply(Math,arr[i]));
}
return newArray;
}
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);
var largestNumbers = new Array();
function largestOfFour(arr) {
for (var i = 0 ; i< arr.length; i ++) {
largestNumbers.push(Math.max.apply(Math, arr[i]));
}
}
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);
Using the approach with Math.max.apply() you can do that with one loop that iterates through the array as argument;
function largestOfFour(arr){
var result = [];
for(var i = 0 ; i < arr.length ; i++){
result[i] = Math.max.apply(null, arr[i]);
}
return result;
}
EDIT:
As #Jeff Shaver posted a simpler solution, you should use the map function to return the result array.