How to customize this already custom jQuery sort solution? - javascript

i found the following solution to add sorting capabilities to jQuery (ref: jQuery sort()). I've altered the solution to sort strings of unknown length. It works nicely, however as you might notice from the function name: it sorts acscending :-).
jQuery.fn.sort = function() {
return this.pushStack( [].sort.apply( this, arguments ), []);
};
function sortStringAscending(a,b){
var h1 = a.innerHTML;
var h2 = b.innerHTML;
var c = 0;
var str1 = null,
var str2 = null;
while(str1 == str2 && (c < h1.length && c < h2.length)) {
str1 = h1.substring(c,c+1).toLowerCase().charCodeAt(0);
str2 = h2.substring(c,c+1).toLowerCase().charCodeAt(0);
if(str1 > str2) {
r = 1;
} else if(str2 > str1) {
r = -1;
}
c += 1;
}
return r;
};
The function is used like this:
$('ol li').sort(sortStringAscending).appendTo('ol');
Is it possible to alter this code in such a way that the following will become possible?
$('ol li').sort(sortString, 0).appendTo('ol'); //0 for descending
$('ol li').sort(sortString, 1).appendTo('ol'); //1 for ascending

You are not going to be able to easily get an additional argument into the array sort function that the jQuery.fn.sort uses.
It will be easier to use two separate functions, one for ascending, and one for descending, but keep the actual comparision in a third function.
function sortStringAscending(a,b) {
return sortString(a,b,1);
};
function sortStringDescending(a,b) {
return sortString(a,b,-1);
};
function sortString(a,b,direction) {
var h1 = a.innerHTML.toLowerCase();
var h2 = b.innerHTML.toLowerCase();
if(h1 > h2) {
r = 1*direction;
} else if(h2 > h1) {
r = -1*direction;
}
return r;
};
Also note that you can simply compare two strings, there is no need to compare them character by character, unless you want to have unpredictable sort order for items like "abc" and "abcd".
Then you should be able to do
$('ol li').sort(sortStringAscending).appendTo('ol');
$('ol li').sort(sortStringDescending).appendTo('ol');

This will do what you've asked: (use a parameter to decide sort order)
function sortString(a,b,direction){
var d = (direction?1:-1);
var h1 = a.html();
var h2 = b.html();
var c = 0;
var str1 = null,
var str2 = null;
while(str1 == str2 && (c < h1.length && c < h2.length)) {
str1 = h1.substring(c,c+1).toLowerCase().charCodeAt(0);
str2 = h2.substring(c,c+1).toLowerCase().charCodeAt(0);
if(str1 > str2) {
r = 1*d;
} else if(str2 > str1) {
r = -1*d;
}
c += 1;
}
return r;
};

Changing this:
if(str1 > str2) {
r = 1;
} else if(str2 > str1) {
r = -1;
}
to this:
if(str1 > str2) {
r = -1;
} else if(str2 > str1) {
r = 1;
}
will swap the sort order.
EDIT:
Because of the way Javascript's array.sort(callback) function work it is not easy to just add a third parameter for the callback to accept, I will suggest using 2 separate functions mySortAsc and mySortDesc which in turn could be calling a third function and passing whatever parameters are needed.

You might be able to use a closure. Although the javascript array sort method expects a 2 parameter function, you can bring other information into the callback function's scope by doing something like:
function BiSort(direction)
{
return function( a, b )
{
var d = ( direction ? 1 : -1 ) ;
return ( a > b ? 1 : b > a ? -1 : 0 ) * d ;
}
}
The BiSort function returns a new function that has access to the outer function's parameter list. Now you can do this:
var a = ["ant", "goat", "bat", "zebra", "yak"] ;
a.sort(BiSort(true)); // sorts ascending
a.sort(BiSort(false)); // sort descending

I know this is old, but for future reference, I would make the 2 functions for asc/desc, then make a var point to one or the other based on what you need and then pass that var to the array.sort()
function SortAsc(a, b){
}
function SortDesc(a, b){
}
var sortOrder
// if asc button clicked
sortOrder = SortAsc;
// if desc button clicked
sortOrder = SortDesc;
$('ol li').sort(sortOrder);

Related

Reverse a string using two-pointer method in JS

I am trying to reverse a string. I am aware of .reverse function and other methods in Js to do so, but i wanted to do it this two-pointer method.
The problem is the string is not getting updated. Is there anything i am not aware of strings. Whats wrong here ?
function reverseString(s) {
let lengthOfStr = 0;
if ((s.length - 1) % 2 == 0) {
lengthOfStr = (s.length - 1) / 2
} else {
lengthOfStr = ((s.length - 1) / 2) + 1;
}
let strLengthLast = s.length - 1;
for (let i = 0; i <= lengthOfStr; i++) {
let pt1 = s[i];
let pt2 = s[strLengthLast];
s[i] = pt2;
s[strLengthLast] = pt1;
console.log('----', s[i], s[strLengthLast]);
strLengthLast--;
}
return s;
}
console.log(reverseString('hello'));
Unlike in C, strings in JavaScript are immutable, so you can't update them by indexing into them. Example:
let s = 'abc';
s[1] = 'd';
console.log(s); // prints abc, not adc
You'd need to do something more long-winded in place of s[i] = pt2;, like s = s.substring(0, i) + pt2 + s.substring(i + 1);, and similarly for s[strLengthLast] = pt1; (or combine them into one expression with 3 calls to substring).
I'm not sure why it doesnt update the string, but if you handle the replacement as an array/list it works as follows:
function reverseString(s) {
let lengthOfStr = 0;
sSplit = s.split("");
if ((s.length - 1) % 2 === 0) {
lengthOfStr = (s.length - 1) / 2
}
else {
lengthOfStr = ((s.length - 1) / 2) + 1;
}
let strLengthLast = s.length - 1;
for (let i = 0; i <= lengthOfStr; i++) {
let pt1 = sSplit[i];
let pt2 = sSplit[strLengthLast];
sSplit[i] = pt2;
sSplit[strLengthLast] = pt1;
console.log('----', sSplit[i], sSplit[strLengthLast],sSplit);
strLengthLast--;
}
return sSplit.join("");
}
console.log(reverseString('Hello'));
returns: Hello => olleH
As covered in comment, answers and documentation, strings are immutable in JavaScript.
The ability to apparently assign a property value to a primitive string value results from early JavaScript engine design that temporarily created a String object from primitive strings when calling a String.prototype method on the primitive. While assigning a property to the temporary object didn't error, it was useless since the object was discarded between calling the String method and resuming execution of user code.
The good news is that this has been fixed. Putting
"use strict";
at the beginning of a JavaScript file or function body causes the compiler to generate a syntax error that primitive string "properties" are read-only.
There are many ways of writing a function to reverse strings without calling String.prototype.reverse. Here's another example
function strReverse(str) {
"use strict";
let rev = [];
for( let i = str.length; i--;) {
rev.push(str[i]);
}
return rev.join('');
}
console.log( strReverse("Yellow") );
console.log( strReverse("").length);
I tried that way, hopefully might be helpful for someone.
const input = 'hello'; /*input data*/
const inputArray = [...input]; /*convert input data to char array*/
function reverseString(inputArray) {
let i = 0;
let j = inputArray.length -1 ;
while(i < j ) {
const temp = inputArray[i];
inputArray[i] = inputArray[j];
inputArray[j] = temp;
i++;
j--;
}
};
reverseString(inputArray);
console.log(inputArray)
const finalResult = inputArray.join("");
console.log(finalResult);
Thanks.

javascript - sorting array by order of another array

My goal is to sort this div
<div id="myDiv">3xOrange;2xBlue;1xRed;1xRed;1xRed;1xOrange;2xBlue;3xRed;1xBlue;1xRed;2xBlue;3xRed;1xBlue;1xRed;2xBlue;3xRed;1xBlue;1xRed;2xBlue;3xRed;1xBlue;1xRed;2xOrange;3xRed;1xBlue;1xRed;2xBlue;3xRed;1xBlue;1xRed;20xBlue;33xRed;20xBlue;33xRed;2xBlue;3xRed;51xBlue;51xRed;</div>
by another div in this order
<div id="array"> Blue: 1,Red: 2,Orange: 3, </div>
So my Wanted result is to get result like this
2xBlue;1xBlue;1xBlue;2xBlue;3xRed;3xRed;1xRed;1xRed;2xOrange;3xOrange ......
I aware for the first div needs to be used string split something like this .split('x')[1];
So far I have this code:
var init_arr;
var scorer;
window.onload=function() {
scorer=document.getElementById("array").innerHTML;
init_arr = document.getElementById("myDiv").innerHTML;
var final_arr = init_arr.sort(function(a,b) {
return scorer[a]-scorer[b];
});
}
alert(final_arr);
but getting error TypeError: init_arr.sort is not a function I guess init_arr and scorer are objects not strings
Please Help
This answer deletes the rest of the strings with ; or ,, treats array like a part of a JSON string, and sort with the part after the x.
window.onload = function() {
var init_arr = document.getElementById("myDiv").innerHTML.split(';'),
scorer = JSON.parse('{' + document.getElementById("array").innerHTML + '}');
init_arr.sort(function(a, b) {
var aa = a.split('x')[1],
bb = b.split('x')[1];
return scorer[aa] - scorer[bb];
});
alert(init_arr);
};
<div id="myDiv">3xOrange;2xBlue;1xRed;1xRed;1xRed;1xOrange;2xBlue;3xRed;1xBlue;1xRed;2xBlue;3xRed;1xBlue;1xRed;2xBlue;3xRed;1xBlue;1xRed;2xBlue;3xRed;1xBlue;1xRed;2xOrange;3xRed;1xBlue;1xRed;2xBlue;3xRed;1xBlue;1xRed;20xBlue;33xRed;20xBlue;33xRed;2xBlue;3xRed;51xBlue;51xRed</div>
<div id="array">"Blue": 1,"Red": 2,"Orange": 3</div>
But I really suggest to use real arrays for data and objects for sorting order. And not any parts of HTML code.
Well, I felt dummy after playing around to help you after seeing the first answer, but here it goes.
<div id="myDiv">3xOrange;2xBlue;1xRed;1xRed;1xRed;1xOrange;2xBlue;3xRed;1xBlue;1xRed;2xBlue;3xRed;1xBlue;1xRed;2xBlue;3xRed;1xBlue;1xRed;2xBlue;3xRed;1xBlue;1xRed;2xOrange;3xRed;1xBlue;1xRed;2xBlue;3xRed;1xBlue;1xRed;20xBlue;33xRed;20xBlue;33xRed;2xBlue;3xRed;51xBlue;51xRed;</div>
<div id="array"></div>
var init;
var final;
var scorer;
scorer = document.getElementById("array");
init = document.getElementById("myDiv");
init = init.textContent.split(/\;/);
init = init.filter(function(item) {
return item.length > 0;
})
.map(function(item) {
item = item.split(/x/);
var obj = {
color: item[1],
amount: parseInt(item[0])
}
return obj;
});
final = init.reduce(function(scored, item) {
if(scored[item.color] === undefined) {
scored[item.color] = 0;
}
scored[item.color] += item.amount;
return scored;
}, {});
final = Object.keys(final)
.sort(function(item1, item2) {
return final[item1].amount - final[item2].amount;
})
.map(function(key) {
return key + ' :' + final[key];
});
scorer.textContent = final.join(', ');
At least it was funny to play with map, filter, reduce and sort
This is the sort of thing you could do:
function sort() {
var scorer;
var scorerLookup;
var sortedLookup;
//First we figure out the sort order
scorer = document.getElementById("array").innerHTML.split(',');
scorer.sort(function(a, b) {
aVal = parseInt(a.split(':')[1].trim());
bVal = parseInt(b.split(':')[1].trim());
return aVal - bVal;
});
console.log(scorer);
//Now put the sort order into an object so we can easily lookup values
scorerLookup = {};
for (var i = 0; i < scorer.length; i++) {
var tempVal = scorer[i].split(':');
scorerLookup[tempVal[0].trim()] = parseInt(tempVal[1].trim());
}
console.log(scorerLookup);
//Now sort the main list
init_arr = document.getElementById("myDiv").innerHTML.split(';');
init_arr.sort(function(a, b) {
aVal = scorerLookup[a.split('x')[1]];
bVal = scorerLookup[b.split('x')[1]];
return aVal - bVal;
});
console.log(init_arr);
}
window.onload=sort();
It needs more error trapping really (for blank values, etc) - but it should give you the general idea.

Split a variable using mathematical equations in javascript

I have two questions actually.
What I want to do is 1st to check if the user entered value is a correct mathematical equation. For example, if the use enters x + y ( z this should detect as an invalid formula and x + y ( z ) as a correct one,
The 2nd thing I want to do is to split the formula from the + - * / () signs, so the above formula will be return as x, y, z.
What I have done is bellow
var arr = [];
var s = 'x + y ( z )';
arr = s.split("(?<=[-+*/])|(?=[-+*/])");
console.log(arr);
This returns a single array with just one data like, [x + y ( z )]
Another thing, the variables are not single letters. they could be
words like, annual price, closing price, etc
Can someone help me in this problem. Thanks in advance
UPDATE : I have tried "/[^+/*()-]+/g" also
For the second part:
var s = 'x + y ( z )';
var arr = s.match(/(\w)/g);
console.log(arr);
document.write(JSON.stringify(arr));
Of course, you have to check the validity of the input first.
Edit: using Tomer W's answer suggesting eval():
function checkExpression(str) {
// check for allowed characters only
if (/[^\w\d\(\)\+\*\/\-\s]/.exec(s) != null)
return false;
// extract variable names, assuming they're all one letter only
var arr = s.match(/(\w+)/g);
// instantiate the variables
arr.forEach(function (variable) {
eval(variable + '= 1');
});
// ( is alone, replace it by * (
str = str.replace(/\(/g, '* (');
try {
eval(str);
return true;
}
catch (ex) {
console.log(ex);
return false;
}
}
It's dirty but it works most of the time (Tomer W pointed some edge cases like ++62+5 or 54++++6 that can be avoided with an another regex check), do you have more complicated example to test?
Word of warning
VERY VERY VERY DANGEROUS METHOD AHEAD !!!
I am posting this as it is a valid answer, but you should do it only with extreme caution as a user can totally mess up your site.
DO not let the one user input be used in eval for another user !!! EVER !!!
Actual answer
You can use the built-in java-script compiler of your browser, and use eval()
function checkEq(equ)
{
for(ch in equ){
// check that all characters in input are "equasion usable"
if(" +-*/1234567890e^&%!=".indexOf(ch) === -1)
{ // if there are invalid chars
return false;
}
}
try{
// try running the equ, will throw an exception on a syntax error.
eval(equ);
return true; // no exception
}
catch(ex){
return false; // syntax error
}
}
Plunker example
and as i noted before! extreme caution!
Using both #ShanShan and #Tomer W answers, I wrote a formula validator. the code is bellow. In this validator, I checks for opening and closing brackets, extra / * - + signs, unwanted symbols, etc.
If the user wants to create and validate a formula with x,y,z
variables, user have to add the variables to an array and pass it to
this validator with the formula written so the validator accepts the
variables which are not numbers.
I also used a custom set mentioned in this post. https://stackoverflow.com/a/4344227/918277
Important : This java script function can't validate very complex formulas with sin, cos, tan, log, etc. Script will identify them as just letters and will return false.
function StringSet() {
var setObj = {}, val = {};
this.add = function(str) {
setObj[str] = val;
};
this.contains = function(str) {
return setObj[str] === val;
};
this.remove = function(str) {
delete setObj[str];
};
this.values = function() {
var values = [];
for ( var i in setObj) {
if (setObj[i] === val) {
values.push(i);
}
}
return values;
};
}
/**
*
* #param _formulaInputs
* Array of use entered inputs to be use in formula
* #param _formula
* User entered formula
* #returns {Boolean}
*/
function validateFormula(_formulaInputs, _formula) {
var formula = _formula;
var bracketStack = new Array();
var formulaDescArray = [];
var formulaDescInForm = new StringSet();
for (var i = 0; i < _formulaInputs.length; i++) {
formulaDescInForm.add(_formulaInputs[i]);
}
/* Regex to check for unwanted symbols(! # # $ etc.) */
if (/[^\w\d\(\)\+\*\/\-\s]/.exec(formula) != null) {
return false;
}
for (var i = 0; i < _formula.length; i++) {
if ((_formula.charAt(i) == '/' || _formula.charAt(i) == '*'
|| _formula.charAt(i) == '-' || _formula.charAt(i) == '+')
&& (_formula.charAt(i + 1) == '/'
|| _formula.charAt(i + 1) == '*'
|| _formula.charAt(i + 1) == '-' || _formula
.charAt(i + 1) == '+')) {
return false;
}
}
var lastChar = formula.charAt(formula.length - 1);
if (lastChar == '/' || lastChar == '*' || lastChar == '-'
|| lastChar == '+') {
return false;
}
formulaDescArray = formula.split(/[\/\*\-\+\()]/g);
/* Remove unwanted "" */
for (var i = 0; i < formulaDescArray.length; i++) {
if (formulaDescArray[i].trim().length == 0) {
formulaDescArray.splice(i, 1);
i--;
}
}
/* Remove unwanted numbers */
for (var i = 0; i < formulaDescArray.length; i++) {
if (!isNaN(formulaDescArray[i])) {
formulaDescArray.splice(i, 1);
i--;
}
}
for (var i = 0; i < formulaDescArray.length; i++) {
if (!formulaDescInForm.contains(formulaDescArray[i].trim())) {
return false;
}
}
for (var i = 0; i < formula.length; i++) {
if (formula.charAt(i) == '(') {
bracketStack.push(formula.charAt(i));
} else if (formula.charAt(i) == ')') {
bracketStack.pop();
}
}
if (bracketStack.length != 0) {
return false;
}
return true;
}

Array text to numbers, find matching values and sort

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.

Splicing a row into a Javascript object at an index based upon its value

If I have a javascript object that looks like the following:
{
0: [0,50],
1: [25,50],
2: [148,60]
}
How can I insert a new row at an index dependant on the value?
E.g. if the row I wish to insert contains the data [122,65] I need to test the value '122' versus the first value of all the the rows and then 'splice' the row in at the returned index. The second of each row value (50,50,50 in the example above) should not be taken into consideration. In this case the newd data should be inserted as row 2 since it is less than 148 and higher than 25... With the previous row 2 now becoming row 3.
I have been hunting high and low for an answer to this today and have stumbled across the following code which hints at the kind of functionality I am after, but does not quite work in this instance since if my understaning is correct, it only compares single numbers.
function findInsertionPoint(sortedArr, val, comparator) {
var low = 0, high = sortedArr.length;
var mid = -1, c = 0;
while(low < high) {
mid = parseInt((low + high)/2);
c = comparator(sortedArr[mid], val);
if(c < 0) {
low = mid + 1;
}else if(c > 0) {
high = mid;
}else {
return mid;
}
//alert("mid=" + mid + ", c=" + c + ", low=" + low + ", high=" + high);
}
return low;
}
/**
* A simple number comparator
*/
function numComparator(val1, val2) {
if(val1 > val2) {
return 1;
}else if(val1 < val2) {
return -1;
}
return 0;
}
I don't know if the above code will help anyone come up with a solution but I thought I would share it anyway. I am of course open to any javascript/jQuery method of achieving this.
Thank you.
This code could be improved greatly, but this really is a bandaid for a bad design.
var myObj = {
0: [0,50],
1: [25,50],
2: [148,60]
}
function makeArray( obj ) {
var newArray = [];
for( var x in obj ) {
newArray.push(obj[x]);
}
return newArray;
}
function makeObject( newArray ) {
var newObj = {};
for(var i=0, n=newArray.length; i<n; i++) {
newObj[i] = newArray[i];
}
return newObj;
}
function custSortFnc(a,b) {
return (a[0]==b[0]) ? a[1]>b[1] : (a[0] > b[0]) ? 1 : -1;
}
function addValue(val) {
var newArray = makeArray( myObj );
newArray.push( val );
newArray.sort( custSortFnc );
myObj = makeObject( newArray );
}
console.log(myObj);
addValue([122,65]);
for(var xx in myObj){
console.log(xx + ":" + myObj[xx]);
}
The looping will be bad if you add tons of elements to this thing. I also did not really check the sort function, it could be wrong.
This is never going to work properly as objects do not have a defined order for their properties.
Therefore, inserting a property in an order is not going to always work. Use an array if the order matters.

Categories