So I have a question about this score table I made in html.
var puntenTelling= new Array(3,4,2,1,5);
var teamNamen = new Array(puntenTelling[0]+"Team1", puntenTelling[1]+"Team2",puntenTelling[2]+ "Team3", puntenTelling[3]+"Team4", puntenTelling[4]+"Team5");
puntenTelling.sort(function(a, b){return b-a});
teamNamen.sort();
teamNamen.reverse();
for (var i=0; i<5; i++) {
document.write("<tr><td>" + teamNamen[i]);
document.write("<td>" + puntenTelling[i] + "</td></tr>");
}
Basically this gives me a sorted table, which is sorted on points, and sorted on the teamnames linked to the points.
I have to include the points (puntenTelling) in the array of the teamNames since otherwise I can't sort it in the same way I can sort the points.
Now I am printing it out like this:
Teamname Points
5Team5 5
4Team2 4
3Team1 3
2Team3 2
1Team4 1
I would just like to get rid of the "5,4,3,2,1"
before the "Team5,Team2" etc.
How can I do this?
Your approach of concatenating points and team names is not very clean and robust (how about a team named 1860 Munich?) Much better would be to make an array of objects that contain both team name and its points, and work with this array:
var teamsWithPoints = [
{ name: "team1", points: 3 },
{ name: "team2", points: 4 },
{ name: "team3", points: 2 },
{ name: "team4", points: 1 }
];
teamsWithPoints.sort(function(a, b) { return b.points - a.points });
document.write("<table>");
teamsWithPoints.forEach(function(team) {
document.write("<tr>");
document.write("<td>" + team.name);
document.write("<td>" + team.points);
});
Seems to me that you need a dictionary (associative array) where the keys represent the team's order in the list. Sort the array by the keys, then just print the values. It could even be multidimensional where the key is the desired ranking position and the value contains the team name and the points.
When you're making the array, you're creating objects like this.
var teamNamen = new Array(puntenTelling[0]+"Team1", puntenTelling[1]+"Team2",puntenTelling[2]+ "Team3", puntenTelling[3]+"Team4", puntenTelling[4]+"Team5");
If you don't want the value to be included in the string value, you'd declare teamNamen like so.
var teamNamen = new Array("Team1", "Team2","Team3","Team4","Team5");
However, this will make your original sort not function properly. So you could try this following code to maintain the proper sorting functionality, while printing the correct value.
for (var i=0; i<5; i++) {
document.write("<tr><td>" + teamNamen[i].substring(1));
document.write("<td>" + puntenTelling[i] + "</td></tr>");
}
Related
I created a table called "morning" in AppLab, and one column stores data as an array (or list as it calls it). I'm able to properly add data to this array, but my problem is reading the data back (as I want to display it as a label/normal text on another page) If the numbers 1234 and 5678 are the values in the array, when I try to do
console.log(records[i].id + ': ' + records[i].buses);
The second value (buses) is the name of the column I'm trying to read back, which will result in "," rather than "1234,5678" and I'm not really sure what to do. This is the code I have so far, any help would be greatly appreciated!
readRecords("morning", {}, function(records) {
for (var i =0; i < records.length; i++) {
console.log((records[i]).id + ': ' + records[i].(buses[i]));
}
});
var ts1Buses = ["1234"];
var ts1Change;
onEvent("enterTS1", "click", function(event) {
appendItem(ts1Buses, getText("textTS1"));
updateRecord("morning", {id:1, buses:ts1Buses}, function(record, success) {
setText("textTS1", "");
});
});
The console.log statement in your longer block of code doesn't look quite right. try console.log(records[i].id + ': ' + records[i].buses); instead. if that doesn't work, please post a link to your project so that others can try to find a fix by remixing and editing it.
App Lab's data tables do not support arrays. They will have to be converted into comma-separated strings before creating or updating and converted to an array after reading.
To convert an array to a string, simply use the toString() method:
var array = ["a", "b", "c"];
console.log(array.toString()) // "a,b,c"
To convert a string into an array, use the split() method:
var string = "a,b,c";
console.log(string.split(","); // ["a", "b", "c"]
My arrays:
var mexicanFood = ["Taco Bell", "Beans", "Taco Time", "Buritos", "Chalupa"];
var asianFood = ["Noodles", "Rice", "Sushi", "Fish", "Chicken"];
var americanFood = ["Hot dogs", "Pizza", "Burgers", "Nachos", "Other"];
Know this is a possibility to grab randomly from array:
var randomIndex = Math.floor(Math.random() * mexicanFood.length);
I want to pull a value from each food category. I don't want all of mexicanFood values to be the result for food options. I want it at random but at least to pull one or two from each category. How can you do that with having it go into radio buttons (maybe 5 radio buttons) and can it be done with Math.random?
Also want it to be in javascript and html if possible
Edit:
I basically want different food categories in arrays. Then have random values pulled from the categories and those values will be put into radio buttons. My overall project that I want to create is a voting poll for restaurants to eat at. So I don't want 5 burger places to come up when I have mexican, asian, american, and other options to randomly pull from.
What I am stuck on is how to randomly pull from each array. I know how to randomly pull from one array list. But when I have mexicanFood, asianFood and americanFood (or even more than those), I am not sure how to randomly pull values from those and have those values populate radio buttons
I'm assuming you want to return an array of random foods, containing at least 1 from each category.
I've created a function called createRandomArray(), which accepts an arraySize. This arraySize refers to the amount of items you wish to have in your final array.
In the function, I'm concatenating all of the food arrays together. I'm then looping through this array to add a random index to a new array.
var mexicanFood = ["Taco Bell", "Beans", "Taco Time", "Buritos", "Chalupa"],
asianFood = ["Noodles", "Rice", "Sushi", "Fish", "Chicken"],
americanFood = ["Hot dogs", "Pizza", "Burgers", "Nachos", "Other"];
function createRandomArray(arraySize) {
var allFoods = mexicanFood.concat(asianFood).concat(americanFood),
randomFoods = [];
if (arraySize <= allFoods.length) {
randomFoods = [
mexicanFood[getRandomArrayIndex(mexicanFood)],
asianFood[getRandomArrayIndex(asianFood)],
americanFood[getRandomArrayIndex(americanFood)]
]; // at at least one from each
// remove the ones that were initially added from each
allFoods.splice(allFoods.indexOf(randomFoods[0]), 1);
allFoods.splice(allFoods.indexOf(randomFoods[1]), 1);
allFoods.splice(allFoods.indexOf(randomFoods[2]), 1);
for (var i = 0; i < arraySize - 3; i++) {
var randomIndex = getRandomArrayIndex(allFoods);
randomFoods.push(allFoods[randomIndex]);
allFoods.splice(randomIndex, 1);
}
return randomFoods;
}
return allFoods; // requesting more items of food than the amount available, so just add them all
}
function getRandomArrayIndex(array) {
return Math.floor(Math.random() * array.length);
}
var randomFoods = createRandomArray(5);
for (var i = 0; i < randomFoods.length; i++) {
document.getElementById('food-form').innerHTML += '<input type="radio" name="food" value="' + randomFoods[i] + '"> ' + randomFoods[i] + '<br>';
}
<form action="" id="food-form"></form>
I'm brand new to programming so I apologize if this is a simple question.
I had a unique practice problem that I'm not quite sure how to solve:
I'm dealing with two arrays, both arrays are pulled from HTML elements on the page, one array is representing a bunch of states, and the next array is representing their populations. The point of the problem is to print the name of the states and their less than average populations.
To find and print all of the populations that are less than the average I used this code:
function code6() {
// clears screen.
clr();
// both variables pull data from HTML elements with functions.
var pop = getData2();
var states = getData();
var sum = 0;
for( var i = 0; i < pop.length; i++ ){
sum += parseInt( pop[i], 10 );
var avg = sum/pop.length;
if (pop[i] < avg) {
println(pop[i]);
// other functions used in the code to get data, print, and clear the screen.
function getData() {
var dataSource = getElement("states");
var numberArray = dataSource.value.split('\n');
// Nothing to split returns ['']
if (numberArray[0].length > 0) {
return(numberArray);
} else {
return [];
}
}
// Get the data from second data column
function getData2() {
var dataSource = getElement("pops");
var numberArray = dataSource.value.split('\n');
// Nothing to split returns ['']
if (numberArray[0].length > 0) {
return(numberArray);
} else {
return [];
}
}
// Clear the 'output' text area
function clr() {
var out = getElement("output");
out.value = "";
}
// Print to the 'output' HTML element and ADDS the line break
function println(x) {
if (arguments.length === 0) x = '';
print(x + '\n');
}
Now I just need to know how to get the value of these positions within the array so I can pull out the same positions from my states array and display them both side by side. Both arrays have the identical amount of items.
I hope this makes sense and thanks in advance to anyone who has time to take a look at this.
Best regards,
-E
Its a little hard to tell what you are trying to accomplish, but I guess you are going for something like:
'use strict'
function code6() {
const populations = ['39000000', '28000000', '21000000'];
const stateNames = ['california', 'texas', 'florida'];
const states = populations.map((population, i) => ({
'name': stateNames[i],
'population': Number(population),
}));
const sum = states.reduce((sum, state) => sum + state.population, 0);
const average = sum / populations.length;
states
.filter(state => state.population < average)
.forEach(state => {
const name = state.name;
const population = state.population;
console.log(`state name: ${name}, population: ${population}`);
});
}
// run the code
code6();
// state name: texas, population: 28000000
// state name: florida, population: 21000000
I took the liberty of refactoring your code to be a little more modern (es6) and Idiomatic. I hope its not to confusing for you. Feel free to ask any questions about it.
In short you should use:
'use strict' at the top of your files
const/let
use map/filter/forEach/reduce to iterate lists.
use meaningfull names
, and you should avoid:
classic indexed for-loop
parseInt
, and pretty much never ever use:
var
If your states array is built with corresponding indices to your pop one, like this:
states; //=> ['Alabama', 'Alaska', 'Arizona', ...]
pop; //=> [4863300, 741894, 6931071, ...]
then you could simply update your print statement to take that into account:
if (pop[i] < avg) {
println(state[i] + ': ' + pop[i]);
}
Or some such.
However, working with shared indices can be a very fragile way to use data. Could you rethink your getData and getData2 functions and combine them into one that returns a structure more like this the following?
states; //=> [
// {name: 'Alabama', pop: 4863300}
// {name: 'Alaska', pop: 741894},
// {name: 'Arizona', pop: 6931071},
// ...]
This would entail changes to the code above to work with the pop property of these objects, but it's probably more robust.
If your pop and state looks like:
var state = ['state1', 'state2', ...];
var pop = ['state1 pop', 'state2 pop', ...];
Then first of all, avg is already wrong. sum's value is running along with the loop turning avg's formula into sum as of iteration / array length instead of sum of all pops / array length. You should calculate the average beforehand. array.reduce will be your friend.
var average = pop.reduce(function(sum, val){return sum + val;}, 0) / pop.length;
Now for your filter operation, you can:
Zip up both arrays to one array using array.map.
Filter the resulting array with array.filter.
Finally, loop through the resulting array using array.forEach
Here's sample code:
var states = ['Alabama', 'Alaska'];
var pop = [4863300, 741894];
var average = pop.reduce(function(sum, val){return sum + val;}) / pop.length;
console.log('Average: ' + average);
states.map(function(state, index) {
// Convert 2 arrays to an array of objects representing state info
return { name: state, population: pop[index] };
}).filter(function(stateInfo) {
console.log(stateInfo);
// Filter each item by returning true on items you want to include
return stateInfo.population < average;
}).forEach(function(stateInfo) {
// Lastly, loop through your results
console.log(stateInfo.name + ' has ' + stateInfo.population + ' people');
});
Suppose I have the following array:
var articles = [
{
id: 7989546,
tags: [
"98#6",
"107#6",
"558234#7"
]
},
//...
]
Each element of this array represents (partially) some kind of content in our website. It has an id and is tagged with people (#6) and/or topics (#7).
The user is going to be provided a cookie containing the suggested or recommended tags, like this:
var suggestions = [
"46#6",
"107#6",
"48793#7"
]
Consider these tags like suggestions that will be shown to the end user, like "Maybe you are interesed in reading..."
The suggestions array is already ordered by tag prioritiy. This means, that the first tag is more relevant to the user than the second tag.
Now, what I want to do is to order my articles array in the same way, that is, by tag priority.
No filters should be applied as the articles array is guaranteed to have elements that have at least one tag from the suggestions array.
If I have an article with tags: [ "98#6", "107#6", 558234#7" ] and another one with tags: [ "46#6", "36987#7" ], I want the latter to be first, because the tag 46#6 has more priority than 107#6 in the suggestions array.
How can I achieve this kind of ordering (using two arrays)?
Note: jQuery solutions are gladly accepted.
jsFiddle Demo
Just make your own sort function and then use .indexOf in order to check for tag existence. The issue that you are going to have to decide to handle on your own is what makes the most sense for collisions. If an article is tagged with a priority 1 tag, but another article is tagged with 3 lower priority tags, who gets precedence? There is some logic involved there and in my suggested solution I simply just take a total of the priority by using the length of suggestions and summing the priorities. This can be adapted to give a different type of collision detection if you wish, but the approach will be basically the same.
Step 1: Create the compare function
This is going to order the array descending base on the result from tagCount. Which is to say that if tagCount returns a value of 6 for right, and a value of 3 for left, then 6 is ordered first.
var compareFn = function(left,right){
return tagCount(right.tags) - tagCount(left.tags);
};
Step 2: Create the tagCount "algorithm" for determining priority
This simply gives precedence to the earliest occurring match, but will also give some weight to multiple later occurring matches. It does this by taking the matched index subtracted from the length of the match array (suggestions). So if there are 5 suggestions, and the first suggestion is matched, then that is going to end up being a value of 5 (length=5 - index=0).
var tagCount = function(tags){
var count = 0;
for(var i = 0; i < tags.length; i++){
var weight = suggestions.indexOf(tags[i]);
if(weight > -1)
count += tags.length - weight;
}
return count;
}
Stack Snippet
var articles = [
{
id: 7989546,
tags: [
"107#6",
"558234#7"
]
},
{
id: 756,
tags: [
"98#6",
"558234#7"
]
},
{
id: 79876,
tags: [
"98#6",
"107#6",
"558234#7"
]
},
{
id: 7984576,
tags: [
"98#6",
"107#6",
"46#6"
]
}
];
var suggestions = [
"46#6",
"107#6",
"48793#7"
];
var compareFn = function(left,right){
return tagCount(right.tags) - tagCount(left.tags);
};
var tagCount = function(tags){
var count = 0;
for(var i = 0; i < tags.length; i++){
var weight = suggestions.indexOf(tags[i]);
if(weight > -1)
count += tags.length - weight;
}
return count;
}
var a = articles.sort(compareFn);
console.log(a);
document.querySelector("#d").innerHTML = JSON.stringify(a);
<div id="d"></div>
My approach: Sort by sum of relevance score
Give you have:
var articles = [
{
id: 7989546,
tags: [
"98#6",
"107#6",
"558234#7"
]
},
{
id: 8000000,
tags: [
"107#6",
"107#10",
"558234#7",
"5555#1"
]
},
{
id: 8333000,
tags: [
"46#6",
"107#6",
"666234#7",
"107#6"
]
}
];
var suggestions = [
"46#6",
"107#6",
"48793#7"
];
And you want to sort articles by tags whereas tag ranks are defined in suggestions. One simple approach would be:
Step 1) For each article, get index of each tag exists in the suggestion. If it doesn't exist, discard.
Given suggestions ["a","b","c"]
Article tags ["a","b","zzzz","yyyy"]
Will be mapped to index [0,1] (last two tags are discarded because they do not exist in suggestion list)
Step 2) Calculate degree of relevance. Higher-ranked tag (smaller index) yields greater value (see function degreeOfRelevance() below).
Step 3) Sum the total degree of relevance and sort by this value. Thus, the article which contains higher ranked tags (based on suggestions) will yield higher total score.
Quick example:
article <100> with tags: [a,b,c]
article <200> with tags: [b,c]
article <300> with tags: [c,d,e,f]
Given suggestions: [a,b,c]
The articles will be mapped to scores:
article <100> index : [0,1] ===> sum score: 3+2 = 5
article <200> index : [1] ===> sum score: 2
article <300> index : [2] ===> sum score: 1
Therefore, the article <100> is ranked the most relevant document when sorted by score
And below is the working code for this approach:
function suggest(articles, suggestions){
function degreeOfRelavance(t){
return suggestions.length - suggestions.indexOf(t);
}
function weight(tags){
return (tags.map(degreeOfRelavance)).reduce(function(a,b){
return a+b
},0);
}
function relatedTags(a){
return a.tags.filter(function(t){
return suggestions.indexOf(t)>=0
});
}
articles.sort(function(a,b){
return weight(relatedTags(a)) < weight(relatedTags(b))
});
return articles;
}
// See the output
console.log(suggest(articles,suggestions));
I have two Arrays of object, one has a set of options like this (the left side of the equation):
Id Value
1 Red
2 Blue
3 Green
and another like this (the right side):
Id Value
3 Green
And I need a "left join" (all left products and matching right) like this:
Id Value Selected
1 Red
2 Blue
3 Green X
I would like to create a method with this setup (I put [] to note arrays)
var DisplayArray[] = AllColorsArray[].join(SelectedColors[]);
Is there anything like these already or maybe a JQuery plug-in that does this? It has to be common to provide a selection list with the saved options already checked.
EDIT:
It's really looking for simple SQL like operations on Arrays of objects, but with JavaScript.
use jquery extend, arrays are objects in js:
var object1 = {
apple: 0,
banana: {weight: 52, price: 100},
cherry: 97
};
var object2 = {
banana: {price: 200},
durian: 100
};
$.extend(object1, object2);
In your case will be
var DisplayArray = $.extend(AllColorsArray ,SelectedColors);
You might be interested in LINQ to JavaScript for this sort of thing.
If you set up the arrays in such a way that the indexes are in the same position, you can use a two-dimensional array and then check to see if each dimension is equal. Something like this:
var ary = new Array();
ary[0] = new Array("Red","Blue","Green");
ary[1] = new Array(null, null, "Green");
for (var i in ary[0]) {
alert(ary[0][i] == ary[1][i]); //True if they match, false if not.
}
EDIT
You can manually loop through and check them. You could even throw this in a function where you have to pass the selected and all color arrays. See below for example:
var AllColorsArray = [{"id":1,"value":"Red"},{"id":2,"value":"Blue"},{"id":3,"value":"Green"}];
var SelectedColors = [{"id":3,"value":"Green"}];
for (var ind in AllColorsArray) {
for (var chkind in SelectedColors) {
if (SelectedColors[chkind].id == AllColorsArray[ind].id) {
AllColorsArray[ind] = $.extend(AllColorsArray[ind], SelectedColors[chkind]);
break;
}
}
}
//To test:
for (var i in AllColorsArray) {
alert(AllColorsArray[i].value + ': ' + AllColorsArray[i].selected);
}