The function finds which tv character the user compares to based on their answers to my questions. My code now is very inefficient for multiple select menus!!! Maybe an object that takes all selectmenus in html and allows me to assign array values based on the selected index of a selectmenu.
function onSelectMenuBlur() {
"use strict";
/*list of arrays that will be added to when the user selects an option in a selectmenu.*/
var rickArray = [];
var shaneArray = [];
var bobArray = [];
var carolArray = [];
var lArray = [];
var sm = document.getElementById("selectmenu");
.onchange function that determines what array will be added to depending on the option selected in the select menu. This function will add an array value of 1 once to an array. Seems like an inefficient way, especially with multiple selectmenus!
sm.onchange = function() {
if(sm.selectedIndex + 1 === 1) {
rickArray.push(1);
shaneArray.pop();
bobArray.pop();
carolArray.pop();
lArray.pop();
alert(rickArray.length);
}
else if(sm.selectedIndex + 1 === 2) {
shaneArray.push(1);
rickArray.pop();
bobArray.pop();
carolArray.pop();
lArray.pop();
alert(shaneArray.length);
}
else if(sm.selectedIndex + 1 === 3) {
bobArray.push(1);
rickArray.pop();
shaneArray.pop();
carolArray.pop();
lArray.pop();
alert(bobArray.length);
}
else if(sm.selectedIndex + 1 === 4) {
carolArray.push(1);
rickArray.pop();
shaneArray.pop();
bobArray.pop();
lArray.pop();
alert(carolArray.length);
}
else if(sm.selectedIndex + 1 === 5) {
lArray.push(1);
rickArray.pop();
shaneArray.pop();
bobArray.pop();
carolArray.pop();
alert(lArray.length);
}
else{}
};
.onblur purpose to find array with biggest length or value out of all selectmenus to determine which person associated with the array the user is like. Again seems like an inefficient way to handle!
sm.onblur = function() {
var rickL = rickArray.length;
var shaneL = shaneArray.length;
var bobL = bobArray.length;
var carolL = carolArray.length;
var lL = lArray.length;
// unfinished if else statement !!
if(rickL > shaneL && rickL > bobL && rickL > carolL && rickL > lL) {
alert("you are Rick Grimes");
}
else{
alert("you are someone else");
}
};
}
Use a 2-dimensional array instead of separate arrays for each character, and then use the selected index as an index into the array.
var characters = [[], [], [], [], []];
sm.onchange = function() {
for (var i = 0; i < characters.length; i++) {
if (i == this.selectedIndex) {
characters[i].push(1);
alert(characters[i].length);
} else {
characters[i].pop();
}
}
};
To get the character names in there, make it an array of objects.
characters = [
{ name: "Rick",
array: []
},
{ name: "Carol",
array: []
},
...
}
Then you would use characters[i].array.push(1). And then when you want to say which character they are, find the object with the longest array and then print its .name.
I have an array which looks like this:
["1,8", "4,6,8", "8,9", "6,9"]
1/ I would like to turn it in to this
[1,8,4,6,8,8,9,6,9]
2/ I would then like to find matching values, by looking for the most number:
[8]
This first has been solved with this:
var carArray = ["1,8", "4,6,8,7,7,7,7", "8,9", "6,9"];
//1) create single array
var arr = carArray.join().split(',');
//2) find most occurring
var counts = {}; //object to hold count for each occurence
var max = 0, maxOccurring;
arr.forEach(function(el){
var cnt = (counts[el] || 0); //previous count
counts[el] = ++cnt;
if(cnt > max && cnt > 1){ //only register if more than once (cnt>1)
max=cnt;
maxOccurring = el;
}
});
if(maxOccurring){
//there was an element more than once, maxOccuring contains that element
setResult('Most occuring: ' + maxOccurring + ' (' + max + ' times)');
}
else{
//3)/4) ???
setResult('sorting?');
}
//below is only for test display purposes
function setResult(res){
console.log(res);
}
3/ If the are no matching values like this
[1,8,4,6,5,7]
4/ Then I need to compare this array to another array, such as this
[6,7,4,1,2,8,9,5]
If the first number in <4> array above appears in <3> array, then get that number, ie in the above example I need to get 6. The <4> array will be static values and not change. The numbers is <3> will be dynamic.
EDIT Not the most elegant of answers, but I do have something working now. I didn't compare the original array directly with the second array, instead used simple if/else statements to do what I needed:
var carArray = ["1,5", "4", "8,2", "3,9,1,1,1"];
//1) create single array
var arr = carArray.join().split(',');
//2) find most occurring
var counts = {}; //object to hold count for each occurence
var max = 0, maxOccurring;
arr.forEach(function(el){
var cnt = (counts[el] || 0); //previous count
counts[el] = ++cnt;
if(cnt > max && cnt > 1){ //only register if more than once (cnt>1)
max=cnt;
maxOccurring = el;
}
});
if(maxOccurring){
//there was an element more than once, maxOccuring contains that element
console.log('Most occuring: ' + maxOccurring + ' (' + max + ' times)');
console.log(maxOccurring);
}
else {
// If not occuring, match from a list
if(jQuery.inArray("6", arr) !== -1) { console.log('6'); }
else if(jQuery.inArray("9", arr) !== -1) { console.log('9'); }
else if(jQuery.inArray("7", arr) !== -1) { console.log('7'); }
else if(jQuery.inArray("5", arr) !== -1) { console.log('5'); }
else if(jQuery.inArray("4", arr) !== -1) { console.log('4'); }
else if(jQuery.inArray("1", arr) !== -1) { console.log('1'); }
else { console.log('not found'); }
}
Example Fiddle
Step 1 is fairly easy by using javascript's join and split methods respectively:
var arr = carArray .join().split(',');
For step 2, several methods can be used, the most common one using an object and using the elements themselves as properties. Since you only need to get the most occurring value if there is a reoccurring value, it can be used in the same loop:
var counts = {}; //object to hold count for each occurence
var max = 0, maxOccurring;
arr.forEach(function(el){
var cnt = (counts[el] || 0); //previous count
counts[el] = ++cnt;
if(cnt > max && cnt > 1){ //only register if more than once (cnt>1)
max=cnt;
maxOccurring = el;
}
});
After the above, the variable maxOccurring will contain the reoccurring value (if any) and max will contain the times it occured
For step 4 the easiest way is to loop through the compare array and get the element that occurs in the input array:
var cmpArr = ['6','7','4','1','2','8','9','5'];
//find the first occurrence inside the cmpArr
res = function(){ for(var i= 0 ; i < cmpArr.length; i++){ if(arr.indexOf(cmpArr[i]) !== -1)return cmpArr[i];}}();
The above uses an in place function which is called immediately to be able to use return. You could also just use a loop and assign res when found, then break from the loop.
Last update, an alternate fiddle where the above is converted to a single function: http://jsfiddle.net/v9hhsdny/5/
Well first of all the following code results in four matching answers since the jQuery selectors are the same.
var questionAnswer1 = $(this).find('input[name=questionText]').val();
var questionAnswer2 = $(this).find('input[name=questionText]').val();
var questionAnswer3 = $(this).find('input[name=questionText]').val();
var questionAnswer4 = $(this).find('input[name=questionText]').val();
var carArray = [questionAnswer1, questionAnswer2, questionAnswer3, questionAnswer4];
You could use the eq(index) method of jQuery to select the appropriate element. However having 4 inputs with the same name is a bad practice.
Well lets say that the carArray has 4 different values which all consist out of comma separated numbers. You could then do the following:
var newArr = [];
carArray.forEach(function(e) {
e.split(",").forEach(function(n) {
newArr.push(n);
});
});
Well then we got to find the most occurring number. JavaScript doesn't have any functions for that so we will have to find an algorithm for that. I found the following algorithm on this stackoverflow page
var count = function(ary, classifier) {
return ary.reduce(function(counter, item) {
var p = (classifier || String)(item);
counter[p] = counter.hasOwnProperty(p) ? counter[p] + 1 : 1;
return counter;
}, {})
}
var occurances = count(newArr);
It isn't clear to me what you're trying to do in step 3 and 4, so can't answer those at the moment.
var ary = ["1,8", "4,6,8", "8,9", "6,9"];
var splitted = ary.reduce(function(acc, item) {
return acc.concat(item.split(','));
}, []);
var occurences = splitted.reduce(function(acc, item) {
if (!acc.hasOwnProperty(item)) acc[item] = 0;
acc[item] += 1;
return acc;
},{}),
biggest = Object.keys(occurences).reduce(function (acc, key) {
if (occurences[key] > acc.occurences) {
acc.name = key;
acc.occurences = occurences[key];
}
return acc;
},{'name':'none','occurences':0}).name;
var vals=["1,8", "4,6,8", "8,9", "6,9"];
// 1) turn into number array
var arrNew=[];
for(var i=0; i<vals.length; i++)
{
arrLine=vals[i].split(",");
for (var j=0;j<arrLine.length;j++) { arrNew.push (parseInt(arrLine[j])) }
}
//result:
alert(arrNew.join(";");
// 2) find most common
var found=[];
for(var i=0; i<arrNew.length; i++) {
// make an array of the number of occurrances of each value
if (found["num"+newArray[i]]) {
found["num"+newArray[i]] ++ ;
} else {
found["num"+newArray[i]]=1;
}
}
var mostCommon={count:0,val:"ROGUE"};
for (x in found) {
if (found[x] > mostCommon.count) {
mostCommon.count=found[x].count;
mostCommon.val=x;
}
}
// result :
alert(mostCommon.val);
//3) not quite sure what you meant there
// 4) unique values:
// at this point the 'found' list contains unique vals
var arrUnique=[];
for (x in found) {
arrUnique.push[x];
}
// result :
alert(arrUnique.join(";"))
//sort:
arrUnique.sort(function(a, b){return a-b});
(This won't work in most browsers) but on a side note, when ES6 becomes widely supported, your solution could look like this:
var arr1 = ["1,8", "4,6,8", "8,9", "6,9"];
var arr2 = arr1.join().split(',');
var s = Array.from(new Set(arr2)); //Array populated by unique values, ["1", "8", "4", "6", "9"]
Thought you might like to see a glimpse of the future!
1.
var orgArray = ['1,8', '4,6,8', '8,9', '6,9'];
var newArray = [];
for (var i in orgArray) {
var tmpArray = orgArray[i].split(',');
for (var j in tmpArray) {
newArray.push(Number(tmpArray[j]));
}
}
2.
var counts = {};
var most = null;
for (var i in newArray) {
var num = newArray[i];
if (typeof counts[num] === 'undefined') {
counts[num] = 1;
} else {
++(counts[num]);
}
if (most == null || counts[num] > counts[most]) {
most = num;
} else if (most != null && counts[num] === counts[most]) {
most = null;
}
}
I don't understand the question 3 and 4 (what "unique order" means) so I can't answer those questions.
Hei guys, im struggling with a problem here. I selected all elements from body tag into an array like so :
var DOMelementsOrder = [];
var elements = document.querySelectorAll('body > div');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
DOMelementsOrder.push(element);
console.log(DOMelementsOrder[i].offsetLeft);
}
What i'm trying to reach is to sort the tags in array by theyr prop offset left.
The console in for loop return "40,200,85". What i try to achieve is to sort the tags in DOMelementsOrder in order of theyr offsetLeft.
Any help? Thanks in advance.
ONLY WITH PURE JS
EDIT:
What i have tryed:
function bubbleSort(a, b)
{
var swapped;
do {
swapped = false;
for (var i=0; i < a.length-1; i++) {
if (a[i].b > a[i+1].b) {
var temp = a[i].b;
a[i].b = a[i+1].b;
a[i+1].b = temp;
swapped = true;
}
}
} while (swapped);
}
bubbleSort(DOMelementsOrder, DOMelementsOrder.offsetLeft);
console.log(DOMelementsOrder);
Use the Array.prototype.sort method and pass a compare function to compare the values of offsetLeft for each element.
// qSA doesn't return an array, so we have to convert it first
var elements = Array.prototype.slice.call(document.querySelectorAll('body > div'));
// then we can sort
var orderedElements = elements.sort(function(a, b) {
return a.offsetLeft - b.offsetLeft;
});
I have an array which is
var mycart = [{"id":"1","quantity":"10"},{"id":"6","quantity":"20"},{"id":"3","quantity":"30"},{"id":"4","quantity":"40"}];
//new id's which should be updated
var newid = "6";
var newquantity = "5";
Every-time on cart update i want to update the id and value,if id exists i need to update quantity if doesn't i have to create a new object of id,quantity.
Now,i am adding newid which is 6,as you can see id=6 exist in array so it should just update like this -
for(var x=0; x < mycart.length; x++){
if(mycart[x].id == newid ){
var tmpq = mycart[x].quantity;
mycart[x].quantity = parseInt(tmpq) + parseInt(q);
}
else{
alert(mycart[x].id+' = this is not what you are searching');
}
}
now output is :
var mycart = [{"id":"1","quantity":"10"},{"id":"6","quantity":"25"},{"id":"3","quantity":"30"},{"id":"4","quantity":"40"}];
Now i need help to create new object,if that id doesn't exist in the mycart array.
If i use
//new id's which should be created
var newid = "2";
var newquantity = "15";
var temparr = new Array();
var tmpobj ={};
tmpobj["id"]= newid ;
tmpobj["quantity"] = newquantity ;
temparr.push(tmpobj);
mycart.push(temparr);
within the for loop it will create mycart.length times,then i have to filter with $unique() jQuery API which is bad method to follow.
All i need is to create new object with id:value,quantity:value if it doesn't exists,if it exists then just update. Update part working,create part not able to,
Use a variable to detect if you found an old item:
var found = false;
for(var x=0; x < mycart.length; x++){
if(mycart[x].id == newid ){
var tmpq = mycart[x].quantity;
mycart[x].quantity = parseInt(tmpq) + parseInt(q);
found = true;
break;
}
}
if (!found) {
mycart.push ({ id: newid, quantity: newquantity });
}
It would be simpler if you made mycart an object whose keys are the IDs, so you wouldn't have to do a linear search. It would be like this:
var mycart = {
"1": { quantity: 10 },
"6": { quantity: 20 },
...
};
Then your code would be:
if (mycart.hasOwnProperty(newid)) {
mycart[newid] += newquantity;
} else {
mycart[newid] = { quantity: newquantity };
}
What about something like this?
updateCart = function(newid,newquantity,cart){
for(var x=0; x < mycart.length; x++){
if(mycart[x].id == newid ){
var tmpq = cart[x].quantity;
cart[x].quantity = parseInt(tmpq) + parseInt(newquantity);
return;
}
else{
alert(mycart[x].id+' = this is not what you are searching');
}
}
cart.push({"id":newid,"quantity":newquantity});
return;
};
This avoids any 'flag' variables, which IMHO is nice. You could then call it like so:
updateCart("6","5",mycart); //[..{"id":"6","quantity":"25"}..]
updateCart("10","7",mycart); //[..{"id":"10","quantity":"7"}](new array member)
updateCart("1","5",mycart); //[{"id":"1","quantity":"15"}...]
I must agree with the others, though, when they say that you might want to use some sort of key so you don't have to iterate through the array each time.
To create a new item, I would do:
var match = false;
for (var x = 0; x < mycart.length; x++) {
var id = mycart[x].id;
//If there's a match, then item already exists
if (id === newid) {
//Update it
var tmpq = mycart[x].quantity;
mycart[x].quantity = parseInt(tmpq) + parseInt(q); //I'm not sure what q is, but I will leave it since you said it works in your code
match = true;
}
}
//If no match found, create new
if (!match) {
var newItem = {};
newItem.id = newid;
newItem.quantity = newquantity;
mycart.push(newItem);
}
Since there is no reason for the array to contain multiple objects with the same id, I suggest you use an object as the root of the variable, using the id as an array key (+ prefix to avoid confusions) :
var mycart = {"item_1":{"id":"1","quantity":"10"},"item_6":{"id":"6","quantity":"20"},...};
This way you can set/get quantity with mycart["item_"+id].quantity
so you can update it like that :
function updateQuantity(id, quantity){
if(!mycart["item_"+id]){
// create item in cart
mycart["item_"+id] = {"id":id};
}
// update quantity
mycart["item_"+id].quantity = quantity;
}
(forgive me if I use slightly incorrect language - feel free to constructively correct as needed)
There are a couple posts about getting data from JSON data of siblings in the returned object, but I'm having trouble applying that information to my situation:
I have a bunch of objects that are getting returned as JSON from a REST call and for each object with a node of a certain key:value I need to extract the numeric value of a sibling node of a specific key. For example:
For the following list of objects, I need to add up the numbers in "file_size" for each object with matching "desc" and return that to matching input values on the page.
{"ResultSet":{
Result":[
{
"file_size":"722694",
"desc":"description1",
"format":"GIF"
},
{
"file_size":"19754932",
"desc":"description1",
"format":"JPEG"
},
{
"file_size":"778174",
"desc":"description2",
"format":"GIF"
},
{
"file_size":"244569996",
"desc":"description1",
"format":"PNG"
},
{
"file_size":"466918",
"desc":"description2",
"format":"TIFF"
}
]
}}
You can use the following function:
function findSum(description, array) {
var i = 0;
var sum = 0;
for(i = 0; i < array.length; i++) {
if(array[i]["desc"] == description && array[i].hasOwnProperty("file_size")) {
sum += parseInt(array[i]["file_size"], 10);
}
}
alert(sum);
}
And call it like this:
findSum("description1", ResultSet.Result);
To display an alert with the summation of all "description1" file sizes.
A working JSFiddle is here: http://jsfiddle.net/Q9n2U/.
In response to your updates and comments, here is some new code that creates some divs with the summations for all descriptions. I took out the hasOwnProperty code because you changed your data set, but note that if you have objects in the data array without the file_size property, you must use hasOwnProperty to check for it. You should be able to adjust this for your jQuery .each fairly easily.
var data = {};
var array = ResultSet.Result;
var i = 0;
var currentDesc, currentSize;
var sizeDiv;
var sumItem;
//Sum the sizes for each description
for(i = 0; i < array.length; i++) {
currentDesc = array[i]["desc"];
currentSize = parseInt(array[i]["file_size"], 10);
data[currentDesc] =
typeof data[currentDesc] === "undefined"
? currentSize
: data[currentDesc] + currentSize;
}
//Print the summations to divs on the page
for(sumItem in data) {
if(data.hasOwnProperty(sumItem)) {
sizeDiv = document.createElement("div");
sizeDiv.innerHTML = sumItem + ": " + data[sumItem].toString();
document.body.appendChild(sizeDiv);
}
}
A working JSFiddle is here: http://jsfiddle.net/DxCLu/.
That's an array embedded in an object, so
data.ResultSet.Result[2].file_size
would give you 778174
var sum = {}, result = ResultSet.Result
// Initialize Sum Storage
for(var i = 0; i < result.length; i++) {
sum[result[i].desc] = 0;
}
// Sum the matching file size
for(var i = 0; i < result.length; i++) {
sum[result[i].desc] += parseInt(result[i]["file_size"]
}
After executing above code, you will have a JSON named sum like this
sum = {
"description1": 20477629,
"description2": 1246092
};
An iterate like below should do the job,
var result = data.ResultSet.Result;
var stat = {};
for (var i = 0; i < result.length; i++) {
if (stat.hasOwnProperty(result[i].cat_desc)) {
if (result[i].hasOwnProperty('file_size')) {
stat[result[i].cat_desc] += parseInt(result[i].file_size, 10);
}
} else {
stat[result[i].cat_desc] = parseInt(result[i].file_size, 10);
}
}
DEMO: http://jsfiddle.net/HtrLu/1/