I stored variables in an array. Now I need to extract the variables with the highest value and store them in another array.
This is for a javascript program running on a wix website for my daughter.
var kiara = 1;
var rodeo = 3;
var calypso = 3;
var balthazar = 3;
var mistral = 4;
var saya = 4;
var luna = 4;
var points = [{kiara}, {rodeo}, {calypso}, {balthazar}, {mistral}, {saya}, {luna}],
The variables are already in ascending order. So I need the program to figure out that mistral, saya and luna tied at the top position, then to extract these 3 variables (name of the variables + respective values) and store them in another array. If I had a case where a single variable had the highest value, then a single variable would be stored in the new array.
One way is to find the biggest value first with .map and .reduce working together. Then we can get the objects from the points array that have their first properties with value of maxValue and push it to a separate array newArray.
var maxValue = points
.map(function(obj){ return obj[Object.keys(obj)[0]]; }) //map into array of numbers
.reduce(function(a, b){ return Math.max(a, b);}); // return max value
var newArray = points // filter objects with first prop = maxValue
.filter(function(obj){ return obj[Object.keys(obj)[0]] === maxValue; });
Result will be:
[{mistral: 4}, {saya: 4}, {luna: 4}]
Since your array is ordered, you already know the maximun value is at the last position of the array. So first, you can get this value, and then you can use this value to filter elements whose values are equal to this one:
var kiara = 1;
var rodeo = 3;
var calypso = 3;
var balthazar = 3;
var mistral = 4;
var saya = 4;
var luna = 4;
var points = [{kiara}, {rodeo}, {calypso}, {balthazar}, {mistral}, {saya}, {luna}];
// Since array is ordered, highest value is at the last position.
// So, we can get it like this:
let maxVal = Object.values(points[points.length - 1])[0];
console.log(maxVal);
// Now, filter the array with the highest elements
let highest = points.filter(x => Object.values(x)[0] === maxVal);
console.log(highest)
In the case your initial array is not ordered as you have mentioned, then you can proceed with something like this:
var kiara = 1;
var rodeo = 3;
var calypso = 3;
var balthazar = 3;
var mistral = 4;
var saya = 4;
var luna = 4;
var points = [{saya}, {rodeo}, {mistral}, {balthazar}, {luna}, {kiara}, {calypso}];
// Since array is not ordered, we need to get highest value.
// So, we can get it like this:
let maxVal = points.reduce((max, v) => Math.max(Object.values(v)[0], max), null);
console.log(maxVal);
// Now, filter the array with the highest elements
let highest = points.filter(x => Object.values(x)[0] === maxVal);
console.log(highest)
Here is the ES6 way of doing things. The edge case of the list not being in order is taken care of, so the highest values can be anywhere. You can also modify it to get the smallest values. If you have any questions about the code just ask and I will respond.
const kiara = 1;
const rodeo = 3;
const calypso = 3;
const balthazar = 3;
const mistral = 4;
const saya = 4;
const luna = 4;
function getNamesWithHighestPoints(points) {
const hash = {};
for(let i = 0; i < points.length; i++) {
let point = points[i];
let name = Object.keys(point)[0];
let score = Object.values(point)[0];
if(hash[score] === undefined) {
hash[score] = [point];
}
else {
hash[score].push(point);
}
}
let biggestScore = 0;
Object.keys(hash).forEach(pointKey => {
if(biggestScore < pointKey) {
biggestScore = pointKey;
}
});
return hash[biggestScore];
}
const points = [{kiara}, {rodeo}, {calypso}, {balthazar}, {mistral}, {saya}, {luna}];
console.log(getNamesWithHighestPoints(points));
Solution Below. There would be a way to do this with less code, but this will get the job done for you. One thing to remember, for in loops are your friend when working with objects.
var kiara = 1;
var rodeo = 3;
var calypso = 3;
var balthazar = 3;
var mistral = 4;
var saya = 4;
var luna = 4;
var points = [{rodeo}, {calypso}, {balthazar}, {mistral}, {saya}, {luna},{kiara}];
var maxNumberArray = [];
var maxNamesArray = []; // ADDED THIS LINE
var max;
for(var char in points){
for(var name in points[char]){
if(!max){
max = points[char][name];
} else {
if(max < points[char][name]){
max = points[char][name];
}
}
}
}
for(var char in points){
for(var name in points[char]){
if(points[char][name] === max){
maxNumberArray.push(points[char]);
maxNamesArray.push(name); // ADDED THIS LINE
}
}
}
console.log(JSON.stringify(maxNumberArray));
console.log(maxNamesArray); // ADDED this LINE
:)
Related
I have this array of objects to count element frequency in another array using for loop which prints correct output.
counts = {};
counter = 0;
counter_array = [50,50,0,200]; //this is just for example, this array is filled dynamically
for (var x = 0, y = counter_array.length; x < y; x++) {
counts[counter_array[x]] = (counts[counter_array[x]] || 0) + 1;
}
console.log('FREQUENCY: ',counts); //outputs FREQUENCY: {50:2, 0:1, 200:1}
There is another array of arrays:
holder_text_array = [["a",50,0],["b",0,0]]; //example of dynamically filled array
var p = "a";
var i = 0;
while(i < holder_text_array.length){
if (holder_text_array[i][0]==p) {
var s = counts[holder_text_array[i][1]];
console.log('Element: ', holder_text_array[i][1]); //prints 50 for i = 0
console.log('frequency: ',counts[s]); //prints undefined
counter = counts[s];
}
i++;
}
The array of arrays "holder_text_array" consists of elements whose frequency I need to get in the while loop. Can someone tell me where am I wrong?
The frequency is stored in s not in counts[s]
You're logging counts[s] where var s = counts[holder_text_array[i][1]];
You've already got the element from counts in s. Just log the value of s
Apart from that the function works!
counts = {};
counter = 0;
counter_array = [50,50,0,200]; //this is just for example, this array is filled dynamically
for (var x = 0, y = counter_array.length; x < y; x++) {
counts[counter_array[x]] = (counts[counter_array[x]] || 0) + 1;
}
console.log('FREQUENCY: ',counts); //outputs FREQUENCY: {50:2, 0:1, 200:1}
holder_text_array = [["a",50,0],["b",0,0]]; //example of dynamically filled array
var p = "a";
var i = 0;
while(i < holder_text_array.length){
if (holder_text_array[i][0]==p) {
var s = counts[holder_text_array[i][1]];
console.log('Element: ', holder_text_array[i][1]); //prints 50 for i = 0
console.log('frequency: ', s); // CHANGED THIS TO JUST `s`
counter = counts[s];
}
i++;
}
You could take a recursive approach and call the count function again for (nested) arrays with the same counts object.
The result contains the counts of each element.
function getCounts(array, counts = {}) {
for (let i = 0; i < array.length; i++) {
const value = array[i];
if (Array.isArray(value)) {
getCounts(value, counts);
continue;
}
if (!counts[value]) counts[value] = 0;
counts[value]++;
}
return counts;
}
console.log(getCounts([["a", 50, 0], ["b", 0, 0]]));
I figured out the problem. Issue is in initialization.
I changed the following:
var s = counts[holder_text_array[i][1]];
counter = counts[s];
It works this way:
var s = holder_text_array[i][1];
counter = counts[s];
I am trying to develop a calculation and I need to make a for loop that when it's calculated I need to add 3 up,
the code I use is:
var fields = [fieldname140, fieldname879, fieldname886],
result = 0.00;
for(var i = 1, h=fields.length; i<h; i++)
{
if(ABS(1-fields[i])<ABS(1-result)) result = fields[i];
}
return result;
is there a possibility to do so?
function calculate() {
var fields = ['fieldname140', 'fieldname879', 'fieldname886']; var result = '';
var newFields = [];
for(var i = 0; i < fields.length; i++){
var index = fields[i];
var indexName = index.substring(0, 9);
var indexVal = parseInt(index.substring(9));
result = indexName + (indexVal + 3);
newFields.push(result);
//console.log(result);
}
//console.log(newFields);
return newFields;
}
Call this calculate function and get new fields array with increment.
I've looked at some other questions similar to this, but I'm getting my array in a unique way and I can't figure out for the life of my how to change it to a 2D array.
//Special function for adding arrays, just use sumArray on first array with second array in parenthesis
//==========================================
Array.prototype.sumArray = function (arr) {
var sum = this.map(function (num, idx) {
return num + arr[idx];
});
return sum;
}
var array1 = [1,2,3,4];
var array2 = [5,6,7,8];
var sum = array1.sumArray(array2);
Logger.log("sum: " + sum);
//==========================================
var calc = ss.getRangeByName( "calc" );
var target = ss.getRangeByName( "target" );
var current = ss.getRangeByName( "current" );
var left = ss.getRangeByName( "left" );
var gainedEVs = calc.getValues();
var goalEVs = target.getValues();
var oldEVs = current.getValues();
var leftEVs = left.getValues();
//Make everything ints
//==========================================
for(var i = 0; i < oldEVs.length; i++) {
Logger.log(oldEVs.length);
oldEVs[i] = parseInt(oldEVs[i]);
}
for(var i = 0; i < gainedEVs.length; i++) {
gainedEVs[i] = parseInt(gainedEVs[i]);
}
for(var i = 0; i < goalEVs.length; i++) {
goalEVs[i] = parseInt(goalEVs[i]);
}
for(var i = 0; i < leftEVs.length; i++) {
leftEVs[i] = parseInt(leftEVs[i]);
}
//==========================================
var newEVs = [[oldEVs.sumArray(gainedEVs)]];
var newLeft = [[goalEVs.subArray(newEVs)]];
//Now I try to set values and I get the error
current.setValues(newEVs);
I've tried changing the setValues to setValues([newEVs]); but that doesn't work either. Any clue on how I can get my array of newEVs to be the correct height? It has the right number of values, but those values are being stored in columns, not rows. (in this case all of my ranges are 6 rows 1 col)
Since your ranges are small, you don't have to worry too much about performance, so you can convert them from rows to columns using a loop:
var column = [];
for (var i=0; i<newEVs.length; i++){
column.push([newEVs[i]]);
}
current.setValues(column);
I tried to define a 3D array on Google Sheet, but even though I'm using the .slice() method it keeps passing the array by reference.
var temp = [];
for (var a = 0; a<archetypesAll.length; a++) {temp[a] = [0, a].slice();};
var archRank = [];
for (var a = 0; a<21; a++) {archRank[a]= temp.slice();};
archRank[2][1][0] = 'Test';
I want to edit a single element of the matrix but instead the code above just fills every row with the exact same value ('Test'):
3DMatrix[x][1][0] = 'Test'
You can't just copy a multidimensional array by calling slice at the top level, because that will not deep-copy the whole. You have to write your own deepCopy methid, like this:
function allocate(mainDim, ...dims) {
const result = new Array(mainDim);
for (let i = 0; i < result.length; i++) {
result[i] = dims.length > 0 ? allocate(...dims) : 0;
}
return result;
}
function deepCopy(matrix, dims) {
return dims > 1 ? matrix.map(row => deepCopy(row, dims - 1)) : matrix.slice();
}
function test() {
const mx1 = allocate(3,2,2);
mx1[2][1][0] = "Test";
console.log(JSON.stringify(mx1));
const mx2 = deepCopy(mx1, 3);
mx2[2][1][0] = "Copied";
console.log(JSON.stringify(mx1));
console.log(JSON.stringify(mx2));
}
test();
var array = ["Test", "Test"];
var array3d = [[array.slice(0)],[[array.slice(0)]]];
array3d[0][0][0] = "Changed";
console.log(JSON.stringify(array3d)); //[[["Changed","Test"]],[[["Test","Test"]]]]
Try with this instead of slice to get a new array instead of reference:
var temp = [];
for (var a = 0; a < archetypesAll.length; a++) {
temp[a] = JSON.parse(JSON.stringify([0, a]));
}
var archRank = [];
for (var a = 0; a < 21; a++) {
archRank[a]= temp.slice();
}
archRank[2][1][0] = 'Test';
So i tried to apply bubble sort technique to an associative array.
What i tried is making a normal array and then applying bubble sort.
This worked , so now I'm trying to do the same for my associative array but I can't understand why it doesn't work, can someone explain and tell me how to do this?
Normal Array bubble sort code: <-- This one works
var numbers= new Array()
numbers[0] = 22;
numbers[1] = 3;
numbers[2] = 65;
numbers[3] = 75;
numbers[4] = 500;
numbers[5] = 2;
numbers[6] = 44;
for(var i=0; i<numbers.length; i++)
{
if(numbers[i] < numbers[i+1])
{
var tempGetal = numbers[i];
numbers[i] = numbers[i+1];
numbers[i+1] = tempGetal;
}
}
console.log("Smallest number from array is " + tempGetal);
associative array bubble sort code: <-- Doesn't work
var celsius= new Array()
celsius["Monday"] = 22;
celsius["Tuesday"] = 3;
celsius["Wednesday"] = 65;
celsius["Thursday"] = 75;
celsius["Friday"] = 1;
celsius["Saterday"] = 2;
celsius["Sunday"] = 44;
for(var temp in celsius)
{
if(celsius[temp] < celsius[temp+1])
{
var tempGetal = celsius[temp];
celsius[temp] = celsius[temp+1];
celsius[temp+1] = tempGetal;
}
}
console.log("Smallest number from this array is " + tempGetal[temp]);
Can anyone tell me if the method I'm trying to apply is possible?
Thanks in advance!
There are several reasons why your attempt didn't work, but there is a fundamental flaw in your assumption: the order of properties in an object is undefined, so you should not try to rearrange them.
There's really no reason to use sorting for this. Just go through the object once and find the lowest value:
var min = Infinity;
for(var day in celsius) {
if(celsius[day] < min) {
min = celsius[day];
}
}
console.log(min);
A fancier solution:
var celsius = [];
celsius["Monday"] = 22;
celsius["Tuesday"] = 3;
celsius["Wednesday"] = 65;
celsius["Thursday"] = 75;
celsius["Friday"] = 1;
celsius["Saterday"] = 2;
celsius["Sunday"] = 44;
var min = Object
.keys(celsius)
.map(function(key) {
return celsius[key];
})
.reduce(function(last, next) {
return last < next ? last : next;
}, Infinity);
console.log(min);
Other problems with your approach:
Javascript does not have associative arrays. You should generally not create an array and assign named properties to it (that's what objects are for).
If you iterate through an object with for(var temp in celsius), temp will be the property names, not the temperatures or numerical indices.
With the previous bullet in mind, if temp has the value "Monday", then celsius[temp + 1] = tempGetal will assign tempGetal to the property Monday1.
For the record, your bubble sort doesn't work correctly because you should keep sorting until nothing moves, e.g.
// Sort an array of Numbers
function bubbleSort(arr) {
var oneMoved, // flag if one moved
i, // counter
t; // temp variable
do {
// reset flag
oneMoved = false;
// reset counter
i = arr.length - 1;
while (i--) {
// If array members are out of sequence, swap
if (arr[i] > arr[i+1]) {
t = arr[i];
arr[i] = arr[i+1]
arr[i+1] = t;
// Remember that one moved
oneMoved = true;
}
}
// Keep going as long as one moved
} while (oneMoved)
// Not necessary as array sorted in place, but means function
// can be chained
return arr;
}
// Quick test
var arr = [0, 3, 6, -2, 3];
console.log(bubbleSort(arr)); // [-2, 0, 3, 3, 6]