Sorting Javascript array with strings and numbers - javascript

I have a list of elements in an array in Javascript as follows:
myArray = ["Datastore one - free space 34.23GB", "Datastore two - free space 56.23GB",...]
and so on. I would like to sort the array on the freespace, so in the example above Datastore two would be the first element in the array. The array is always constructed with "- free space xx.xxGB", but the free space could be 5 digits in some cases, so xxx.xxGB for example.
Can anyone help provide a way of sorting the array please? I see I can use something like
"*- free space\s[1-9][0-9]*GB"
So would this be like
myArray.sort("*- free space\s[1-9][0-9]*GB") ?
Is this correct or how would I do this? Many thanks in advance.

Pull the numeric parts out in a custom sort function, and subtract:
myArray = ["Datastore one - free space 34.23GB", "Datastore two - free space 56.23GB", "Datastore three - free space 6.23GB" ];
var re = /([0-9\.]+)GB/; // regex to retrieve the GB values
myArray = myArray.sort(
function(a, b) {
var ma = a.match(re); // grab GB value from each string
var mb = b.match(re); // the result is an array, with the number at pos [1]
return (ma[1] - mb[1]);
}
);
alert(myArray.join("\r\n"));

This should do the trick:
myArray.sort(function compare(a, b) {
var size1 = parseFloat(a.replace(/[^0-9\.]/g, ''));
var size2 = parseFloat(b.replace(/[^0-9\.]/g, ''));
if (size1 < size2) {
return -1;
} else if (size1 > size2) {
return 1;
}
return 0;
});
Array.prototype.sort does not accept a regex, it accepts a callback or will do its best to sort your array based on numeric/alphabetical order if you don't pass a callback
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

This should work as well if you just want the numbers returned.
I split the string by spaces and grab the last section. (#GB), I then grab the substring of everything but the last two characters (so I chop off the GB), I then use the Javascript function to sort the remaining numbers.
JSFiddle Demo
window.onload = function() {
myArray = ["Datastore one - free space 34.23GB", "Datastore two - free space 56.23GB", "Datastore two - free space 16.23GB", "Datastore two - free space 6.23GB"];
for (i = 0; i < myArray.length; i++)
{
var output = myArray[i].split(" ").pop();
output = output.substring(0, output.length-2);
myArray[i] = output;
}
myArray.sort(function(a, b){return a-b});
alert(myArray);
};

Related

Sort a list by the second number after a dot

I need to sort a list by the second batch number with JavaScript.
This is how it looks like now:
1101.19
1201.17
1301.09
What I need is:
1301.09
1201.17
1101.19
As I am still learning to program I can't figure out the issue. But need it at work.
Can someone help me understand the process of how to do it?
Sort the array depending on the decimal part. Here is the solution
Sort the array by selecting the decimal part of the number inside the sort function.
You can get the decimal part of any number by taking modulus operation with 0.1. Link.
const arr = [1101.19, 1201.17, 1301.09, 1201.20];
arr.sort((a, b) => {return (a % 1 - b % 1)});
console.log(arr);
You need to split each element before sort and compare second parts
let array = ["1101.69", "1701.57", "1301.09"];
array.sort((a,b)=>{
let pair1 = a.split('.');
let pair2 = b.split('.');
return ( parseInt(pair1[1]) < parseInt(pair2[1])) ? -1 : 1;
});
console.log(array);

Hacker Rank Annagrams

I am trying to solve the problem described here with JavaScript...
https://www.hackerrank.com/challenges/ctci-making-anagrams
I have to output the number of letters that would need to be removed from two strings in order for there to only be matching letters (compare the two strings for matching letters and total the letters that don't match)
for example...
string a = cbe
string b = abc
the only matching letter is between both strings is the two c's so I would be removing 4 letters (beab).
My code works, but it seems to keep timing out. If I download the individual test case instances, I seem to fail when variables a and b are set to large strings. If I test these individually, I seem to get the right output but i still also get the message "Terminated due to timeout".
I'm thinking it might be obvious to someone why my code timesout. I'm not sure it's the most elegant way of solving the problem but I'd love to get it working. Any help would be much appreciated...
function main() {
var a = readLine();
var b = readLine();
var arraya = a.split('');
var arrayb = b.split('');
var arraylengths = arraya.length + arrayb.length;
//console.log(arraylengths);
if (arraya.length <= arrayb.length) {
var shortestarray = arraya;
var longestarray = arrayb;
} else {
var shortestarray = arrayb;
var longestarray = arraya;
}
var subtract = 0;
for (x = 0; x < shortestarray.length; x++) {
var theletter = shortestarray[x];
var thenumber = x;
if (longestarray.indexOf(theletter, 0) > -1) {
var index = longestarray.indexOf(theletter, 0);
longestarray.splice(index, 1);
subtract = subtract + 2;
}
}
var total = arraylengths - subtract;
console.log(total);
}
Your algorithm is good. It's straight forward and easy to understand.
There are certain things you can do to improve the performance of your code.
You don't have to calculate the indexOf operation twice. you can reduce it to one.
the splice operation is the costliest operation because the JS engine has to delete the element from an array and reassign the indexes of all the elements.
A point to be noted here is that the JS engine does an extra step of correcting the index of the array, which is not required for your purpose. So you can safely remove longestarray.splice(index, 1); and replace it with delete longestarray[index]
Here is a snippet which will increase your performance of the code without changing your logic
for (var x = 0; x < shortestarray.length; x++) {
var theletter = shortestarray[x];
var thenumber = longestarray.indexOf(theletter, 0); // <-- check only once
if (thenumber > -1) {
var index = thenumber;
delete longestarray[index]; // <-- less costlier than splice
subtract = subtract + 2;
}
}
Note: I am not suggesting you to use delete for all the cases. It's useful here because you are not going to do much with the array elements after the element is deleted.
All the best. Happy Coding
I would suggest you hashing. make the characters of string key and its numbers of occurrences value. Do the same for both strings. After that take string 1 and match the count of its every character with the count of same character in string then calculate the difference in the number of occurrences of the same character and delete that character till the difference becomes 0 and count that how many times you performed delete operation.
ALGORITHM:
step 1: Let arr1[255]= an integer array for storing the count of string1[i]
and initialized to zero
ex: string1[i]='a', then arr1[97]=1, because ASCII value of a is 97
and its count is 1. so we made hash table for arr1 where key is
ASCII value of character and value is its no of occurrences.
step 2: Now declare an another array of same type and same size for string 2
step 3: For i=0 to length(string1):
do arr1[string1[i]]++;
step 4: For i=0 to length(string2):
do arr2[string2[i]]++;
step 5: Declare an boolean char_status[255] array to check if the
character is visited or not during traversing and initialize it to
false
step 6: set count=0;
step 7: For i=0 to length(string1):
if(char_status[string1[i]]==false):
count=count+abs(arr1[string1[i]]-arr2[string1[i]])
char_status[string1[i]]=true
step 8: For i=0 to length(string2):
if(char_status[string2[i]]==false):
count=count+abs(arr1[string2[i]]-arr2[string2[i]])
char_status[string2[i]]=true
step 9: print count
I have applied this algo just now and passed all test cases. You may improve this algo more if you have time.

using the digits of a number as an array

var number = 342345820139586830203845861938475676
var output = []
var sum = 0;
while (number) {
output.push(number % 10);
number = Math.floor(number/10);
}
output = output.reverse();
function addTerms () {
for (i = 0; i < output.length; i=i+2) {
var term = Math.pow(output[i], output[i+1]);
sum += term;
}
return sum;
}
document.write(output);
document.write("<br>");
document.write(addTerms());
I am trying to take that large number and split it into its digits. Then, find the sum of the the first digit raised to the power of the 2nd, 3rd digit raiseed to the 4th, 5th raised to the 6th and so on. for some reason, my array is returning weird digits, causing my sum to be off. the correct answer is 2517052. Thanks
You're running into precision issues within JavaScript. Just evaluate the current value of number before you start doing anything, and the results may surprise you:
>>> var number = 342345820139586830203845861938475676; number;
3.423458201395868e+35
See also: What is JavaScript's highest integer value that a Number can go to without losing precision?
To resolve your issue, I'd store your input number as an array (or maybe even a string), then pull the digits off of that.
This will solve your calculation with the expected result of 2517052:
var number = "342345820139586830203845861938475676";
var sum = 0;
for(var i=0; i<number.length; i=i+2){
sum += Math.pow(number.charAt(i), number.charAt(i+1));
}
sum;
JavaScript stores numbers in floating point format (commonly double). double can store precisely only 15 digits.
You can use string to store this large number.
As mentioned, this is a problem with numeric precision. It applies to all programming languages that use native numeric formats. Your problem works fine if you use a string instead
var number = '342345820139586830203845861938475676'
var digits = number.split('')
var total = 0
while (digits.length > 1) {
var [n, power] = digits.splice(0, 2)
total += Math.pow(n, power)
}
(the result is 2517052, byt the way!)
Cast the number as a string and then iterate through it doing your math.
var number = "342345820139586830203845861938475676";//number definition
var X = 0;//some iterator
var numberAtX = 0 + number.charAt(X);//number access
The greatest integer supported by Javascript is 9007199254740992. So that only your output is weird.
For Reference go through the link http://ecma262-5.com/ELS5_HTML.htm#Section_8.5
[edit] adjusted the answer based on Borodins comment.
Mmm, I think the result should be 2517052. I'd say this does the same:
var numbers = '342345820139586830203845861938475676'.split('')
,num = numbers.splice(0,2)
,result = Math.pow(num[0],num[1]);
while ( (num = numbers.splice(0,2)) && num.length ){
result += Math.pow(num[0],num[1]);
}
console.log(result); //=> 2517052
The array methods map and reduce are supported in modern browsers,
and could be worth defining in older browsers. This is a good opportunity,
if you haven't used them before.
If you are going to make an array of a string anyway,
match pairs of digits instead of splitting to single digits.
This example takes numbers or strings.
function sumPower(s){
return String(s).match(/\d{2}/g).map(function(itm){
return Math.pow(itm.charAt(0), itm.charAt(1));
}).reduce(function(a, b){
return a+b;
});
}
sumPower('342345820139586830203845861938475676');
alert(sumPower(s))
/*
returned value:(Number)
2517052
*/

jquery Tablesorter - natural sort order?

I've looked through all the answers listed for tablesorter but can't find what I'm looking for.
I have a table which I'm trying to sort, one column contains product model numbers which include both letters and numbers, the problem is that it sorts alphabetically but not with the numbers in their proper order. For example the sorted column comes out like this:
STRB 18,
STRB 19,
STRB 2,
STRB 20,
STRB 23 - you get the idea.
I've gathered that I need this column to sort in natural order, but I've not got any js chops to do this with. If anybody could point me in the right direction I would be very grateful!
taken from some old code of mine
compare = {
natural: function(a, b) {
function prepare(s) {
var q = [];
s.replace(/(\D)|(\d+)/g, function($0, $1, $2) {
q.push($1 ? 1 : 2);
q.push($1 ? $1.charCodeAt(0) : Number($2) + 1)
});
q.push(0);
return q;
}
var aa = prepare(a), bb = prepare(b), i = 0;
do {
if(aa[i] != bb[i])
return aa[i] - bb[i];
} while(aa[i++] > 0);
return 0;
}
}
example of use
test = ['img100b', 'img21', 'img18', 'img100a', 'img1', 'img2']
console.log(test.sort(compare.natural))
The jquery tablesorter plugin offers the ability to write your own parser.
Check out the example and give it a shot!
http://tablesorter.com/docs/example-parsers.html
Not sure what you mean by "natrual" order, but I am guessing you mean that strb 2 would be before strb 18.
The order you have above is correct for strings. if you want to sort by the number portion (assuming all the strb's are always the same) you will have to do a substring to get the number only and then sort the data.
I would also NOT do this in javascript. Let your database work for you and let it handle the order of the data. It will save you a lot of pain.

JavaScript: check if an array is a subsequence of another array (write a faster naïve string search algo)

[5, 4, 4, 6].indexOfArray([4, 6]) // 2
['foo', 'bar', 'baz'].indexOfArray(['foo', 'baz']) // -1
I came up with this:
Array.prototype.indexOfArray = function(array) {
var m = array.length;
var found;
var index;
var prevIndex = 0;
while ((index = this.indexOf(array[0], prevIndex)) != -1) {
found = true;
for (var i = 1; i < m; i++) {
if (this[index + i] != array[i]) {
found = false;
}
}
if (found) {
return index;
}
prevIndex = index + 1
}
return index;
};
Later I have find wikipedia calls it Naïve string search:
In the normal case, we only have to look at one or two characters for each wrong position to see that it is a wrong position, so in the average case, this takes O(n + m) steps, where n is the length of the haystack and m is the length of the needle; but in the worst case, searching for a string like "aaaab" in a string like "aaaaaaaaab", it takes O(nm) steps.
Can someone write a faster indexOfArray method in JavaScript?
The algorithm you want is the KMP algorithm (http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm) used to find the starting index of a substring within a string -- you can do exactly the same thing for an array.
I couldn't find a javascript implementation, but here are implementations in other languages http://en.wikibooks.org/wiki/Algorithm_implementation/String_searching/Knuth-Morris-Pratt_pattern_matcher -- it shouldn't be hard to convert one to js.
FWIW: I found this article a good read Efficient substring searching It discusses several variants of Boyer-Moore although it's not in JavaScript. The Boyer-Moore-Horspool variant (by Timo Raita’s -- see first link for link) was going to be my "suggestion" for a potential practical speed gain (does not reduce big-O though -- big-O is upper limit only!). Pay attention to the Conclusion at the bottom of the article and the benchmarks above.
I'm mainly trying to put up opposition for the Knuth-Morris-Pratt implementation ;-)

Categories