This is what code looks like:
var figury = new Array("kwadrat", "kolo", "trojkat_rownoboczny", "trojkat_prostokatny", "heksagon", "trapez");
var kolory = new Array("blue", "green", "red", "yellow");
var losowanie_figur = function(wylosowane_figury) {
for(var i = 0; i <= 3; i++)
wylosowane[i] = { figura: figury[losowe[i]] };
}
var losowanie_kolorow = function(wylosowane_kolory) {
for(var i = 0; i <= 3; i++)
wylosowane[i] = { kolor: kolory[losowe[i]] };
}
What I want to do is to update the array with the color values but what I get is that the previous values are being overwritten. I'm using a random f
This is what I get:
{ '0': { kolor: 'red' },
'1': { kolor: 'green' },
'2': { kolor: 'yellow' },
'3': { kolor: 'blue' } }
And what I really wanted is:
{ '0': { figura: 'kwadrat', kolor: 'green' },
'1': { figura: 'heksagon', kolor: 'red' },
'2': { figura: 'trapez', kolor: 'blue' },
'3': { figura: 'trojkat_prostokatny', kolor: 'yellow' } }
You can do this:
var losowanie_kolorow = function(wylosowane_kolory){
for(var i=0;i<=3;i++)
wylosowane[i].kolor =kolory[losowe[i];
}
You need to set the properties on the objects, rather than setting the whole array value to be a new object.
As an aside you never set up wylosowane in this code, I'm assuming that was cut to simplify? You also never use the parameters of the functions. Since thats the case its probably better to not have the params at all.
Also its generally considered best practice to declare arrays as
var kolory = ["blue", "green", "red", "yellow"];
rather than
var kolory = new Array("blue", "green", "red", "yellow");
Most people consider it more readable, and it avoids some weird edge cases (new Array(3) for instance, creates an empty array of length 3, rather than an array of length 1 with 3 at the 0 index)
You can use underscore JS to achieve something similar to this: http://underscorejs.org/#zip
var figury = new Array("kwadrat", "kolo", "trojkat_rownoboczny", "trojkat_prostokatny", "heksagon", "trapez");
var kolory = new Array("blue", "green", "red", "yellow");
var combined = _.zip(figury, kolory);
Hope this helps
Related
I'm trying to setValue for each cell separately while loop is running.
for (var i = 5; i <= lastRow; i++) { // Start from row 5
var pos = sheet.getRange([i], 1); // 1 == column A, A=1,B=2,C=3 etc.
var posValue = (pos.isPartOfMerge() ? pos.getMergedRanges()[0].getCell(1, 1) : pos).getValue(); // get value of marged cell
var animalColor = sheet.getRange([i], 9); // 9 == column I
if (posValue == 'Cat') {
animalColor.setValue('brown');
} else if (posValue == 'Dog') {
animalColor.setValue('black');
} else if {
animalColor.setValue('none');
}
}
I want to go from this:
To this:
I tried to write additional IF statements but that just felt dumb and code will get heavier.
Create an array of colors for each animal. Then you can get the next value from the appropriate animal's array.
const colors = {
Dog: {
colors: ['white', 'black', 'red', 'grey'],
index: 0
},
Cat: {
colors: ['brown', 'black', 'white', 'gray'],
index: 0
},
Bird: {
colors: ['yellow', 'red', 'blue', 'purple'],
index: 0
}
};
for (var i = 5; i <= lastRow; i++) { // Start from row 5
var pos = sheet.getRange([i], 1); // 1 == column A, A=1,B=2,C=3 etc.
var posValue = (pos.isPartOfMerge() ? pos.getMergedRanges()[0].getCell(1, 1) : pos).getValue(); // get value of marged cell
var animalColor = sheet.getRange([i], 9); // 9 == column I
if (posValue in colors) {
animalColor.setValue(colors[posValue].colors[colors[posValue].index++]);
}
}
Alternate solution
You can use the includes,map and setValues methods in getting the desired output. You may use the script below as a guide.
Script:
const colors = {
"Cat": ["brown", "black", "white", "gray"],
"Dog": ["white", "black", "red", "gray"],
"Bird": ["yellow", "red", "blue", "purple"]
};
function transformTable() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); // Get the active sheet
var range = sheet.getRange("A1:A"); // Get the range of the data
var values = range.getValues().flat().filter(x => x); // Get the values of the data
var animalsInData = Object.keys(colors);
var output = [];
values.map(x => (animalsInData.includes(x))? colors[x].map(y=>output.push([y])) : output.push([""]));
sheet.getRange(1,3,output.length,1).setValues(output); // edit the range accordingly
}
Output:
Please note that I have added snake as a test case if the script will run even if there is an additional animal outside the colors object
References:
setValues method
JavaScript Array map
JavaScript String includes
I'm currently trying to get chart.js 2.0 to automatically generate new colours for dynamic labels. the use case is I'm making a pie chart using data from a database where each row is a new label and the count next to it is the data e.g. MOVIE | VOTES PER MOVIE. however, the problem with this is that I don't know how many rows there will be and therefore can't manually put in colours. I figured a solution may be to automatically generate colours and then use a for loop to insert them in. This is my code:
function getRandomColor() { //generates random colours and puts them in string
var colors = "";
for (var i = 0; i < 3; i++) {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var x = 0; x < 6; x++ ) {
color += letters[Math.floor(Math.random() * 16)];
}
color = "'"+color+"'"+",";
colors += color;
}
colors = colors.slice(0, -1);
console.log(colors);
return colors;
}
const data = {
labels: [
'Red',
'Blue',
'Yellow'
],
datasets: [{
label: 'My First Dataset',
data: [300, 50, 100],
backgroundColor: [
getRandomColor() // calls for 3 random colours
// e.g. returns '#DDA597','#A95647','#78366A'
],
hoverOffset: 4
}]
};
I've noticed that the commas separating them are part of the string so they don't properly separate the colours. However, I can't think of a way around this. Does anyone know of a possible solution to this. Or even a better approach to this problem.
Thanks in advance!
If you push the values to an array imidiatly instead of to a string it will work fine.
Example:
function getRandomColor() { //generates random colours and puts them in string
var colors = [];
for (var i = 0; i < 3; i++) {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var x = 0; x < 6; x++) {
color += letters[Math.floor(Math.random() * 16)];
}
colors.push(color);
}
return colors;
}
const data = {
labels: [
'Red',
'Blue',
'Yellow'
],
datasets: [{
label: 'My First Dataset',
data: [300, 50, 100],
backgroundColor: getRandomColor(),
hoverOffset: 4
}]
};
const options = {
type: 'pie',
data
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
</body>
I'm developing a system where students are added to color groups (RED,BLUE,GREEN,YELLOW). They need to be added evenly. Here is a picture of the logic for adding a student to a group
Here is the logic I have so far (purely based on number of students in each group):
var studentsByColorGroup={"GREEN":[], "BLUE":[], "RED":[], "YELLOW":[]};
var gradeCountsByColorGroup={
"GREEN" :{3:0, 4:0, 5:0, 6:0},
"BLUE" :{3:0, 4:0, 5:0, 6:0},
"RED" :{3:0, 4:0, 5:0, 6:0},
"YELLOW":{3:0, 4:0, 5:0, 6:0}
};
for(var student of students) {
studentsByColorGroup[student.color].push(student);
gradeCountsByColorGroup[student.color][student.grade]++;
}
var greenCount =studentsByColorGroup["GREEN" ].length;
var blueCount =studentsByColorGroup["BLUE" ].length;
var redCount =studentsByColorGroup["RED" ].length;
var yellowCount=studentsByColorGroup["YELLOW"].length;
var list={
"GREEN" :this.greenCount,
"BLUE" :this.blueCount,
"RED" :this.redCount,
"YELLOW":this.yellowCount
};
var keysSorted:string[]=Object.keys(list).sort((a, b) => list[a]-list[b]);
// The first element in the list of sorted keys should
// be the color with the LEAST students in it
newStudent.color=keysSorted[0];
Now, I need to add the part that makes sure that students are balanced as much as possible with respect to grade. Please see the image for details.
How would you alter the above algorithm to programmatically determine the new student's color group?
By the way, this is a real-world problem (not just for student algorithm assignment) for a system I'm developing which goes live next Wednesday
First, pick the elements with the lowest count and then pick the one with the lowest count of the colour of the student. A greedy algorithm will suffice.
const groups = new Map();
// initialize your groups
map.add("red", { ... });
function findGroup(grade) {
const min = "red";
map.forEach((group, color) => {
const groupLength = length(group);
const minLength = length(min[0]);
if(groupLength < minLength) {
min = [color]
} else if(groupLength == minLength && group[grade] < map.get(min)[grade]) {
min = color;
}
});
return min;
}
Lots of editing to make a runable snippet... Key Features though are the following functions:
getEligibleColorsByCounts
accepts an object whose keys are colors and values are numbers
sorts colors by value
populates array by starting with lowest sorted color then adding each additional color that has same value
returns array of colors
getEligibleColorsByTotals
builds object whose keys are colors and values are from studentsByColorGroup
calls getEligibleColorsByCounts passing in object
returns array of colors whose counts are all equal
getEligibleColorsByGrade
builds object whose keys are colors and values are from gradeCountsByColorGroup
calls getEligibleColorsByCounts passing in object
returns array of colors whose counts are all equal
getNewStudentColorGroup
calls getEligibleColorsByTotals
if only one possible color, returns that color
otherwise calls getEligibleColorsByGrade and passes in results of getEligibleColorsbyTotals
returns a single color
addStudent
gets color for new student from getNewStudentColorGroup
adds student to color group array
increments number of students of newStudent.grade in color group
var students = [];
students.push({name: "student1", grade:4});
students.push({name: "student2", grade:6});
students.push({name: "student3", grade:5});
students.push({name: "student4", grade:3});
students.push({name: "student5", grade:6});
students.push({name: "student6", grade:3});
students.push({name: "student7", grade:3});
students.push({name: "student8", grade:3});
var studentsByColorGroup = {
"GREEN": [],
"BLUE": [],
"RED": [],
"YELLOW": []
};
var gradeCountsByColorGroup = {
"GREEN": {
3: 0,
4: 0,
5: 0,
6: 0
},
"BLUE": {
3: 0,
4: 0,
5: 0,
6: 0
},
"RED": {
3: 0,
4: 0,
5: 0,
6: 0
},
"YELLOW": {
3: 0,
4: 0,
5: 0,
6: 0
}
};
var getEligibleColorsByCounts = function(counts) {
var colors = Object.keys(counts);
colors.sort(function(a, b) {
return (counts[a] - counts[b]);
});
var returnArray = [];
for (var index = 0; index < colors.length; index++) {
returnArray.push(colors[index]);
if (index != colors.length - 1) {
if (counts[colors[index]] != counts[colors[index + 1]]) {
break;
}
}
}
return (returnArray);
};
var getEligibleColorsByTotals = function() {
var colorCounts = {
"GREEN": studentsByColorGroup["GREEN"].length,
"BLUE": studentsByColorGroup["BLUE"].length,
"RED": studentsByColorGroup["RED"].length,
"YELLOW": studentsByColorGroup["YELLOW"].length
};
var returnArray = getEligibleColorsByCounts(colorCounts);
return (returnArray);
};
var getEligibleColorsByGrade = function(colors, grade) {
var colorCounts = {};
colors.forEach(function(color) {
colorCounts[color] = gradeCountsByColorGroup[color][grade];
});
var returnArray = getEligibleColorsByCounts(colorCounts);
return (returnArray);
};
var getNewStudentColorGroup = function(grade) {
var returnColor = '';
var totalsColors = getEligibleColorsByTotals();
if (totalsColors.length == 1) {
returnColor = totalsColors[0];
} else {
var gradeColors = getEligibleColorsByGrade(totalsColors, grade);
returnColor = gradeColors[0];
}
return (returnColor);
};
var addStudent = function(student, grade) {
var color = getNewStudentColorGroup(grade);
studentsByColorGroup[color].push(student);
gradeCountsByColorGroup[color][grade]++;
};
students.forEach(function(student){
addStudent(student, student.grade);
});
console.log(studentsByColorGroup);
var newStudent = {};
console.log("Adding Student9");
newStudent = {name: "student9", grade:6};
students.push(newStudent);
addStudent(newStudent, newStudent.grade);
console.log(studentsByColorGroup);
console.log("Adding Student10");
newStudent = {name: "student10", grade:3};
students.push(newStudent);
addStudent(newStudent, newStudent.grade);
console.log(studentsByColorGroup);
console.log("Adding Student11");
newStudent = {name: "student11", grade:4};
students.push(newStudent);
addStudent(newStudent, newStudent.grade);
console.log(studentsByColorGroup);
console.log("Adding Student12");
newStudent = {name: "student12", grade:6};
students.push(newStudent);
addStudent(newStudent, newStudent.grade);
console.log(studentsByColorGroup);
console.log("Adding Student13");
newStudent = {name: "student13", grade:5};
students.push(newStudent);
addStudent(newStudent, newStudent.grade);
console.log(studentsByColorGroup);
Is it possible to create complex objects at runtime in javascript ? If so, what is the correct syntax ?
var food = {};
food["fruit"]["yellow"] = "banana";
food["meat"]["red"] = "steak";
food."fruit"."green" = "apple";
It's not clear what you're trying to do. If you want to build that object up all at once, then you could do something like:
var food = {
fruit: {
yellow: 'banana',
green: 'apple'
},
meat: {
red: 'steak'
}
};
If you need to piece it together one nested object at a time, then you just need to make sure that you are creating a new object to add properties to.
For example, your line:
food["fruit"]["yellow"] = "banana";
will probably fail because food.fruit does not exist.
You should do:
var food = {};
food.fruit = {};
food.fruit.yellow = 'banana';
You could write a function to add data to your object.
e.g.
function addEntry(obj, entry) {
if(entry.length < 2) return;
if(entry.length === 2) obj[entry[0]] = entry[1];
else {
if(!obj[entry[0]] || typeof obj[entry[0]] !== "object") obj[entry[0]] = {};
addEntry(obj[entry[0]], entry.slice(1));
}
}
var data = [
["fruit", "yellow", "banana"],
["meat", "red", "steak"],
["fruit", "green", "apple"]
];
var obj = {};
for(var i = 0; i < data.length; i++) {
addEntry(obj, data[i]);
}
console.log(obj);
I'm new to JavaScript and im confused how to extract a particular key value from a JSON file:
var me = {"fcolors": ["blue", "green", "whitesmoke"],"fire": ["pink", "grey", "red"]};
i want only fcolour values
fcolour = [];
for (var key in me) {
if (me[key] instanceof Array) {
for (var i = 0; i < me[key].length; i++) {
console.log();
fcolour.push(me[key][i])
}
}
}
i want result to be fcolour=["blue", "green", "whitesmoke"]
thanks in advance and any comment is appreciated.....
You dont need to loop to get its value since your json doesnt have array of fcolors:
me.fcolors will give you ["blue", "green", "whitesmoke"]
Plunker Here
For Multiple objects:
var data = [{
"fcolors": ["blue", "green", "whitesmoke"],
"fire": ["pink", "grey", "red"]
}, {
"fcolors": ["red", "white", "yellow"],
"fire": ["black", "gray", "pink"]
}];
var fcolors = [];
for (var i = 0; i < data.length; i++) {
if (data[i].hasOwnProperty('fcolors')) {
fcolors.push(data[i].fcolors);
}
}
console.log(fcolors);
fcolors contains array
Plunker
Why are you looping JSON , when you can easily access given JSON as
me.fcolors; // It will give you ["blue", "green", "whitesmoke"]
If your array is a flat object, using the following will get the wanted value.
var jsonData = {fcolors: [...], fire: [...]};
if (jsonData.hasOwnProperty('fcolors')) {
var fcolors = jsonData.fcolors;
}
If you have multiple similar objects in the array, you could use the following to grab all the values.
var jsonData = [
{fcolors: [...], fire: [...]},
{fcolors: [...], fire: [...]},
{fcolors: [...], fire: [...]}
];
var fcolors = [];
for (var i = 0; i < jsonData.length; i++) {
var current = jsonData[i];
if (current.hasOwnProperty('fcolors')) {
fcolors.push(current.fcolors);
}
}
After which fcolors is a multidimensional array.