Array text to numbers, find matching values and sort - javascript

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.

Related

How do I return only the letter that repeats the most times?

How do I return only the letter that repeats the most times? How to make it return only the result e = 5 in the following case
enter code here
var s = "Teeeeessttt"
var x = (s.toLowerCase());
function count() {
array_elements = ([...x]);;
array_elements.sort();
var current = null;
var cnt = 0;
for (var i = 0; i < array_elements.length; i++) {
if (array_elements[i] != current) {
if (cnt > 0) {
document.write(current + ' - ' + cnt + '<br>');
}
current = array_elements[i];
cnt = 1;
} else {
cnt++;
}
}
if (cnt > 0) {
document.write(current + ' - ' + cnt);
}
}
count();
First you would need to count the amount of times a character occurs. You could use the reduce method to loop over each character and store that character as a key in an object. The value of the key should represent the amount of times the character has occurred.
It would look like the object below.
{
"t": 4,
"e": 5,
"s": 2
}
From here you want to look for the highest number and return the key that corresponds to it. I've borrowed the solution of this SO thread to get the highest count of the object using another reduce loop.
const string = "Teeeeessttt";
const mostOccuringCharacter = string => {
// Count the occurence of each character.
const count = [...string.toLowerCase()].reduce((counter, char) => {
counter[char] = (counter[char] || 0) + 1;
return counter;
}, {});
// Compare the values with each other and return the
// character with the highest count.
const highestChar = Object.keys(count).reduce((a, b) =>
count[a] > count[b] ? a : b);
// Return an array with the character and the count.
return [highestChar, count[highestChar]]
};
const [ char, count ] = mostOccuringCharacter(string);
console.log(`${char} = ${count}`);
#UKS points out a dupe for this, interestingly there was a post with issues with funcky unicode.. eg. πŸ‘¦πŸΏπŸ‘¦πŸ‘¦πŸΏπŸ‘¦πŸ‘¦πŸ»πŸ‘¦πŸ½πŸ‘¦πŸΎπŸ‘¦πŸΏ, but no solution was shown for this.
So with that in mind I thought I would knock up a version that handles unicode nicely. I've also split into multiple functions for re-use. As you can see it's also easy to alter to find the least used character if so wanted. Not sure if this will handle 100% unicode, there might be some even more funcky ones. :)
function unicodeStrSplit(str) {
const x = [...str];
//let handle some funcky unicode
for (let p=x.length-1;p>0;p--)
if(x[p].charCodeAt(0)===0xd83c){x[p-1] += x[p], x.splice(p, 1) };
return x;
}
function arrayCounter(arr) {
return [...arr.reduce((a,v)=>a.set(v,a.get(v)+1||1),new Map())].
sort((a,b) => b[1]-a[1]);
}
function stringCounter(str) {
return arrayCounter(unicodeStrSplit(str));
}
console.log(stringCounter("Teeeeessttt").shift()); //first array item
//funcky unicode too.
console.log(stringCounter('πŸ‘¦πŸΏπŸ‘¦πŸ‘¦πŸΏπŸ‘¦πŸ‘¦πŸ»πŸ‘¦πŸ½πŸ‘¦πŸΎπŸ‘¦πŸΏ').shift()); //first array item
//also let's get the least used
console.log(stringCounter('πŸ‘¦πŸΏπŸ‘¦πŸ‘¦πŸΏπŸ‘¦πŸ‘¦πŸ»πŸ‘¦πŸ½πŸ‘¦πŸΎπŸ‘¦πŸΏ').pop()); //last array item

Find element from 3 arrays

I want to find element from 3 arrays and create string using values. I have tried and given the output. But I want to know that, is there any better solution for this.
var numbers = ['1','2','3','4','5'];
var letters = ['A','B','C','D','E'];
var romans = ['I','II','III','IV','V'];
function findInArray(input){
var index = -1;
if(numbers.indexOf(input) >= 0){
index = numbers.indexOf(input);
} else if(letters.indexOf(input) >= 0){
index = letters.indexOf(input);
} else if(romans.indexOf(input) >= 0){
index = romans.indexOf(input);
}
if(index > -1){
var data = '{"numbers":"'+numbers[index]+'","letters":"'+letters[index]+'","romans":"'+romans[index]+'"}';
console.log(data);
}
}
findInArray('2');
output : {"numbers":"2","letters":"B","romans":"II"}
You don't need to check if indexOf exists for each of the arrays. You can just find the max value of index for all the three arrays.
If the argument exists in any of the array, it will return a positive values (which results in true)
Then you can simply return the concatenation of the result using the template strings
var numbers = ['1','2','3','4','5'];
var letters = ['A','B','C','D','E'];
var romans = ['I','II','III','IV','V'];
var findInArray = (i) => {
var index = Math.max(numbers.indexOf(i), letters.indexOf(i), romans.indexOf(i));
if (index) {
return `{numbers: ${numbers[index]}, letters: ${letters[index]}, romans: ${romans[index]}}`;
}
}
console.log(findInArray('2'));
console.log(findInArray('D'));
console.log(findInArray('V'));
Vishal,
#Jonas has used a self executing function.
For example it will output 25
(function(x){
return x*x;
}(5));
here 5is the parameter of this self executing function which will output to 25
Back to answer; When you convert his answer to raw it will look something like
const findInArray = val => (i => ({ //i = 1 here
numbers: numbers[1],
letters: letters[1],
romans: romans[1]
}))(Math.max(1,-1,-1) //will output 1);
Hope it makes sense.
resource - http://markdalgleish.com/2011/03/self-executing-anonymous-functions/
Might be simpler with:
const findInArray = val => (i => ({
numbers: numbers[i],
letters: letters[i],
romans: romans[i]
}))(Math.max(
numbers.indexOf(val),
letters.indexOf(val),
romans.indexOf(val)
));

Is there a way to pull all select menu’s selected index in my html to add values to different arrays of my choice. A lot of code for 1 select menu

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.

how can i make my function more efficient?

hey guys i wrote a function that compares array values and returns the minimum value but i want to know if there are ways to make it more efficient like iterating through all arrays (using one loop) and putting the results in a new array or making individual arrays sub-arrays of a single array, etc. Also the function provides the correct output but prints the answer three times:
var nums1 = [-7528819, 3927361, -6398192];
var nums2 = [1777100, -2299720, -5566643];
var nums3 = [7188445, 3724971, 7699332];
var nums4 = [-8432528, -159836, -1604959];
var nums5 = [2764889, 4681472, 701396];
var nums6 = [-5073513, 599535, 4388457];
var nums7 = [8689640, 8028586, 1022322];
var nums8 = [-1088592, 1211232, -7868192];
var nums9 = [-5848613, -4945165, 631213];
var nums10 = [3218429, -833619, -1495854];
var nums11 = [8007060, 1637562, -7568493];
var nums12 = [-8391131, -6585338, 131787];
var nums13 = [-3957775, -9396892, -6143241];
var nums14 = [-6258442, -7829421, 3696922];
var nums15 = [2136598, 4935467, -1621605];
var nums16 = [-7162005, 9861954, 8977930];
var nums17 = [7226452, 8551594, 7006517];
var nums18 = [-1751226, -2536997, -1782251];
var nums19 = [380582, 1614389, 3272584];
var nums20 = [-8988205, -5167181, -7561034];
var nums21 = [-484059, -7160121, 4076528];
var nums22 = [1947448, -5551253, 7491190];
var numsLength = nums1.length;
var i = 0;
var minNum;
function test(arr) {
for (i; i < numsLength; i++) {
if (arr[0] < arr[1] && arr[2]) {
minNum = arr[0];
} else if (arr[1] < arr[2] && arr[0]) {
minNum = arr[1];
} else if (arr[2] < arr[1] && arr[0]) {
minNum = arr[2];
}
console.log(minNum);
}
}
test(nums1);
You could just use Math.min function.
console.log(Math.min.apply(null, nums1));
Look at his snippet of code and read inline comments:
var nums = [];
// I'm pushing only 3 sets of data, but there can be any number
// Also there can be any number of elements in each array as you can see
nums.push([-7528819, 3927361, -6398192]);
nums.push([1777100, -2299720, -5566643, 380582]);
nums.push([7188445, 3724971, 7699332, 1947448, -5551253, 7491190]);
function produceResults(nums) {
var i,
results = [];
// gathering results
for (i = 0; i < nums.length; i++) {
results.push(Math.min.apply(null, nums[i]));
}
return results;
}
console.log(produceResults(nums));
So 2 suggestions:
use more dynamic structure (array of arrays) instead of
defining 22 arrays.
use built in JS functions and components (Math.min)
Unrolling a loop is actually the most efficient implementation of a loop in most cases. However, practically speaking, unrolling a loop isn't usually feasible. With a small, fixed-size array, like those you have here, each permutation of the loop is obvious, and if your goal is raw speed you can't get much more efficient than what you have. That being said, the loop in your function is useless, as others have pointed out., because you've essentially unrolled the loop already. Also the syntax of the if statement is incorrect, and you are not handling the case where values in the array are equal. For fixed arrays of size three you want something more along the lines of...
if (val1 <= val2 && val1 <= val3) {
minVal = val1;
} else if (val2 <= val1 && val2 <= val3) {
minVal = val2;
} else minVal = val3;
Now if you want to do an arbitrary search for the min value of any size array you would do something similar, but using a loop, like...
var minVal = null;
for (var i = 0; i < arr.length; i++) {
if (minVal === null || minVal > (val = arr[i]))
minVal = val;
}
Depending on what you actually want to accomplish, and the size of the array, it might make sense to sort the array and rerurn the min (0 index) from the sorted array. If you go that route, start with a google search for "sort algorithms"

count total duplicates in js array

I'm looping through all classnames in my html body.
I'd like to store the classname with textSize value. Each time there is a duplicate value for a given classname, I want to increment its textSize.
$("*").each(function() {
classname = $(this).get(0).className;
myarray.push({"className" : classname, "textSize" : 5});
Here, I attempt to sort the classnames, then get a count for each duplicate:
myarray.sort();
var current = null;
var dupCount = 0;
for (var i = 0; i < myarray.length-1; i++) {
if (myarray[i]["className"] !== "") {
if (myarray.indexOf(myarray[i]["className"]) == -1) {
log(myarray[i]["className"]);
}
else {
log("DUP");
myarray[i]["textSize"] = myarray[i]["textSize"] += 5;
dupCount++;
}
}
}
log(myarray[i]["className"]);, shown in the image below, clearly shows duplicates:
Yet, log("DUP"); is never called once. Why is that?
Moreover, why doesn't myarray.sort(); sort them alphabetically? If it did that, I could just do if (myarray[i]["className"] === myarray[i++]["className"]) { to check if the value equals the next value in the array. But sort doesn't work.
Edit:
So when looping through, I should be able to alter the css per classname, right?
for(var classname in classes) {
console.log(classes[classname].textSize);
var $val = $(classes[classname]);
$val.css({
"color" : "blue",
"fontSize": $val.textSize+"px"
});
}
This doesn't work even though console.log(classes[classname].textSize); gives text sizes per element
Try using an object instead of an array, using class names as the keys:
var classes = {};
$("*").each(function() {
var classname = $(this).get(0).className;
var c = classes[classname] ||
(classes[classname] = { className: classname, textSize: 0 });
c.textSize += 5;
});
for(var classname in classes) {
console.log(classes[classname]);
}
Remember that any element can have multiple classes. If you want to account for that, you'll have to split up the class names:
$("*").each(function() {
var classnames = $(this).get(0).className.split(' ');
for(var i=0; i<classnames.length; i++) {
var classname = classnames[i];
var c = classes[classname] ||
(classes[classname] = { className: classname, textSize: 0 });
c.textSize += 5;
}
});
See this demonstration: http://jsfiddle.net/FSBhv/
UPDATE: the OP clarified that he wants to set the text size on the elements based on the number of elements that have that class. Doing that will take a slightly different approach (we'll actually have to store the elements):
var eltsByClass = {};
$("*").each(function() {
var $this = $(this);
$this.get(0).className.split(' ').forEach(function(cname) {
var c = eltsByClass[cname] ||
(eltsByClass[cname] = []);
c.push($this.get(0));
});
});
for(var cname in eltsByClass) {
var elts = eltsByClass[cname];
$(elts).css('font-size', (elts.length + 1) * 5 + 'px');
}
Store your data in an object, not an Array. And it can be simplified as:
var classes = {};
$("*").each(function() {
var classname = $(this).get(0).className;
classes[classname] = (classes[classname] || 0) + 5;
});
for(var classname in classes) {
console.log(classname + " textSize:" + classes[classname]);
}
myarray.indexOf(myarray[i]["className"]) is a problem.
You know that myarray contains only objects, but you're asking for the position of a string within that list. That's never going to return anything but -1.
Consider using a second array to store the frequency count, instead of trying to do both with myarray.
var frequency = {};
myarray.forEach(function (i) {
frequency[i.className] = frequency[i.className] || 0
frequency[i.className]++;
}
This will hely you to sort array alphabetically based on classname
var myarray=[];
$("*").each(function()
{
classname = $(this).get(0).className;
myarray.push({"className" : classname, "textSize" : 5});
});
function compare(a,b)
{
if (a.className < b.className)
return -1;
if (a.className > b.className)
return 1;
return 0;
}
myarray.sort(compare);

Categories