sorting of array manually in javascript - javascript

I have an array of strings like below.
ABC
QRS
DEF
HIJ
TUV
KLM
NOP
I need to sort this array in javascript in alphabetical order, except for few values which is already known. ie I need DEF and NOP comes in the first 2 positions and sort rest of the array alphabetically in ascending order. Here is what I've written to sort the entire array in alphabetical order, now I need the 2 values in the first 2 positions.
array.sort(function(a,b){return ((a < b) ? -1 : (a > b) ? 1 : 0)});
Expected result.
DEF
NOP
ABC
HIJ
KLM
QRS
TUV
The contents of the array is dynamic, so if the array has DEF or NOP, then those should be on top, if else, it should be sorted alphabetically. Whats the best way to approach this?

I think the most straightforward way would be to remove the known elements separately instead of trying to incorporate them into the sort. That way, you can also just sort without a comparison function.
function sortWithKnownPrefix(prefix, arr) {
// Get the non-prefix elements
var rest = arr.filter(function (item) {
return prefix.indexOf(item) === -1;
});
// Concatenate the prefix and the sorted non-prefix elements
return prefix.concat(rest.sort());
}
sortWithKnownPrefix(
["DEF", "NOP"],
["ABC", "QRS", "DEF", "HIJ", "TUV", "KLM", "NOP"]
)
// ["DEF", "NOP", "ABC", "HIJ", "KLM", "QRS", "TUV"]

If you want to allow for, count and hoist multiple instances of those strings: http://jsfiddle.net/4hgnjqas/1/
The following will count all known instances of the strings you want to hoist to the front, remove them from the existing array, sort it, then add the same number of "DEF"s and "NOP"s to the array.
var hoist = {"NOP":0, "DEF":0}
for(var p in hoist)
while(array.indexOf(p)>-1){
array.splice(array.indexOf(p),1);
hoist[p]++;
}
arr.sort();
for(var p in hoist){
for(var i=0;i<hoist[p];i++)
array.unshift(p);
}
console.log(array);

This will reposition 'DEF' and 'NOP' after sorting the rest of the items:
function customSort(array) {
array = array.sort(function(a,b){
return (a < b) ? -1 : (a > b) ? 1 : 0;
});
var NOPIndex = array.indexOf('NOP');
if (NOPIndex > -1)
array.unshift(array.splice(NOPIndex, 1)[0]);
var DEFIndex = array.indexOf('DEF');
if (DEFIndex > -1)
array.unshift(array.splice(DEFIndex, 1)[0]);
return array;
}

this could be the simpler one
var arr = ['ABC','QRS','DEF','HIJ','TUV','KLM','NOP']
var exclude = ['DEF', 'NOP'];
arr.sort(function(a,b) {
if(exclude.indexOf(a) > -1 && exclude.indexOf(b) > -1)
return ((a < b) ? -1 : (a > b) ? 1 : 0);
if(exclude.indexOf(b) > -1)
return 1;
return ((a < b) ? -1 : (a > b) ? 1 : 0)
});
alert(JSON.stringify(arr)) //result
JS Fiddle *UPDATED

Related

Sort array alphanumerically [duplicate]

This question already has answers here:
Sort mixed alpha/numeric array
(18 answers)
Closed 3 years ago.
I have array like below , I want to sort it alphanumerically by ascending or descending in faster way.
[
"NFO:BANKNIFTY1931428900CE",
"NFO:BANKNIFTY1931429000CE",
"NFO:BANKNIFTY1931429500CE",
"NFO:BANKNIFTY1931429400CE",
"NFO:BANKNIFTY1931429300CE",
"NFO:BANKNIFTY1931429200CE"
]
I want to sort it like below , descending or ascending
[
"NFO:BANKNIFTY1931429500CE",
"NFO:BANKNIFTY1931429400CE",
"NFO:BANKNIFTY1931429300CE",
"NFO:BANKNIFTY1931429200CE",
"NFO:BANKNIFTY1931429000CE",
"NFO:BANKNIFTY1931428900CE",
]
I tried something like below , but it does not sort properly and its slow too.
function sort() {
var arr = disorderedArray;
arr.sort(function(a, b) {
a = a.split(" ");
b = b.split(" ");
var an = parseInt(a[0], 10);
var bn = parseInt(b[0], 10);
return an < bn ? 1 : (an > bn ? -1 : (a[1] < b[1] ? -1 : (a[1] > b[1] ? 1 : 0)));
});
console.log(arr.reverse());
}
Note: Sometimes it can involve mix of lowercase letters.
Simply use .sort().
var items = [
"NFO:BANKNIFTY1931428900CE",
"NFO:BANKNIFTY1931429000CE",
"NFO:BANKNIFTY1931429500CE",
"NFO:BANKNIFTY1931429400CE",
"NFO:BANKNIFTY1931429300CE",
"NFO:BANKNIFTY1931429200CE"
]
var sorted = items.sort()
console.log(sorted);

How to sort set of numbers both lexicographically and numerically?

I currently have a set of strings that are both just numbers and number with + or -. Such as follows :
1 , 1+, 1-, 2, 2+, 2-, 10
Which when I sort using JavaScript's sort functions gives out:
1, 1+ , 1-, 10, 2, 2+, 2-
which is lexicographically orders but not numerically. Is there a way to sort this so the numbers come out in the correct way(the first list) ? I am using ExtJS stores so an answers as a store sorter is preferred but plain javascript is also fine. Thanks ?
Edit: This is not just sorting numbers.
You can use a custom ordering function like so:
var numbers = ['1', '1-', '1+', '2', '2+', '2-', '10'];
numbers.sort(function (a, b){
var _a = parseFloat(a), // If the values are integers only, parseInt will do too
_b = parseFloat(b);
if (_a - _b === 0) {
return (a > b) ? 1 : -1;
} else {
return _a - _b;
}
});
console.log(numbers);
The function checks whether the number values are equal, and if so, falls back to lexicographic ordering to sort the character suffixes. If there are no suffixes in equal-case, hence no matter in which order the numbers are returned. If only one of the operands has a suffix, bare number returns negative. If the number values are not equal, the function simply returns the tristate, i.e a - b, which will be evaluated to one of negative, 0, positive. Or actually it's "bistate", since we've handled 0 case already.
More generic solution
The code above is rather a special case for two different single charactered suffixes only. If suffixes are more complex, here's a more generic code to sort by number and by suffixes:
var numbers = ['1', '1-r', '1+q', '1', '2', '2+q', '2-r', '10'];
function suffixSort (suff, asc) {
asc = 2 * +(!!asc) - 1; // Convert boolean to -1 or 1
return function (a, b) {
var _a = parseFloat(a), // Extract the number value
_b = parseFloat(b),
aSI = -(a.length - _a.toString().length), // Get the index of suffix start
bSI = -(b.length - _b.toString().length);
// Equal number values, sort by suffixes
if (_a === _b) {
return (suff.indexOf(a.substr(aSI)) > suff.indexOf(b.substr(bSI))) ? 1 : -1;
}
// Inequal number values, sort by numbers
return asc * (_a - _b);
}
}
// suffixSort arguments
// suff: An array of the suffix strings to sort, ordered in the desired sorting order
// asc: true = ascending, false = descending. Optional, defaults to descending sort
numbers.sort(suffixSort(['+q', '-r'], true));
console.log(numbers);
The idea is to store the suffixes into an array, and when suffix sorting is needed, function compares the array indices of the suffixes instead of the suffixes themselves.
suffixSort lets you also to decide the sorting direction. Selected sorting direction doesn't have an effect on suffix sorting, they are always returned in the order they appear in suff array.
These values are almost integers, so comparing them according to praseInt will almost get you there. The only thing missing is a special treatment for values that have the same integer part where x- should come first, then x and finally x+:
function specialChar(s) {
c = s.substr(-1);
if (c == '+') {
return 1;
}
if (c == '-') {
return -1;
}
return 0;
}
function numCompare(a, b) {
aNum = parseInt(a);
bNum = parseInt(b);
cmp = aNum - bNum;
if (cmp != 0) {
return cmp;
}
// Integer parts are equal - compare the special char at the end
return specialChar(a) - specialChar(b);
}
arr = ['1' , '1+', '1-', '2', '2+', '2-', '10'];
arr.sort(numCompare);
var result=[];
result=array.map(function(n){
if(typeof n==='number') return n;
if(n[n.length-1]=='+'){
return parseInt(n.substring(0,n.length-1))
}
else if(n[n.length-1]=='-'){
return 0-parseInt(n.substring(0,n.length-1))
}
});
result.sort(function(a,b){return a-b})
You could use Array#sort and split the elements in numbers and the rest, then return the difference or the difference of the order.
var array = ['10', '2', '2+', '2-', '1', '1+', '1-'];
array.sort(function (a, b) {
var r = /\d+|\D+/g,
aa = a.match(r),
bb = b.match(r),
order = { '+': 1, '-': 2 };
return aa[0] - bb[0] || (order[aa[1]] || 0) - (order[bb[1]] || 0);
});
console.log(array);
If there are only three possible states of a number, and the states have the order number, number+, number the states can be recreated by creating an array representation of the numbers, removing the unique numbers from array, from minimum to maximum, concatenating empty string or arithmetic operator in required order to the number, then pushing the value to an array, where .toString() can be used to view the comma separated string representation of the sorted values within the array
var str = `314+, 1-, 7+, 1, 1-, 271-, 10-
, 10+, 271, 271+, 314-, 314
, 10, 2-, 2, 2+, 7-, 7`;
for (var [nums, order, res, num] = [str.match(/\d+/g), ["", "+", "-"], [], null]
; nums.length
; num = Math.min.apply(Math, nums)
, res = [...res, ...order.map(op => num + op)]
, nums = nums.filter(n => n != num)
);
console.log(res.toString() + "\n", res);
Assuming that you just want to throw away the symbols, then you could use parseInt and Array#sort to get order numerically.
var data = ['1' , '1+', '1-', '2', '2+', '2-', '10'];
var sortedData = data.sort(function(a,b){return parseInt(a)-parseInt(b);});

sort an alphanumeric array

I have an array that contains numbers and strings:
disorderedArray = ["74783 Banana", "38903 Orange", "94859 Apple"];
I needed to put them in ascending order by number. I found an example that worked well for descending Sort Alphanumeric String Descending
However, I can't seem to change the return line to make the array ascending. I tried to put arr.reverse(); after the return line, but that seemed kind of hackish and it didn't work anyways. I also changed the > and < symbols in the return line, but I started to get crazy results.
function sort() {
var arr=disorderedArray;
arr.sort(function(a,b){
a=a.split(" ");
b=b.split(" ");
var an=parseInt(a[0],10);
var bn=parseInt(b[0],10);
return an<bn?1:(an>bn?-1:(a[1]<b[1]?-1:(a[1]>b[1]?1:0)));
arr.reverse();
});
console.log(arr);
}
The callback function returns positive or negative values depending on the comparison of the values. Just change the sign of the -1 and 1 values that are returned:
return an<bn?-1:(an>bn?1:(a[1]<b[1]?1:(a[1]>b[1]?-1:0)));
Here is a more readable way to write the same:
return (
an < bn ? -1 :
an > bn ? 1 :
a[1] < b[1] ? 1 :
a[1] > b[1] ? -1 :
0
);
Note that the original code sorts the numeric part descending and the rest of the string ascending, so this does the opposite. The value from the first two comparisons determine how the numeric part is sorted, and the last two determine how the rest of the strings are sorted, so you can adjust them to get the desired combination.
sort's function is just to sort. You need to call reverse on the sorted array.
function sort() {
var arr = disorderedArray;
arr.sort(function(a, b) {
a = a.split(" ");
b = b.split(" ");
var an = parseInt(a[0], 10);
var bn = parseInt(b[0], 10);
return an < bn ? 1 : (an > bn ? -1 : (a[1] < b[1] ? -1 : (a[1] > b[1] ? 1 : 0)));
});
console.log(arr.reverse());
}

JavaScript .sort override

I have an array of strings, which are all similar except for parts of them, eg:
["1234 - Active - Workroom",
"1224 - Active - Breakroom",
"2365 - Active - Shop"]
I have figured out that to sort by the ID number I just use the JavaScript function .sort(), but I cannot figure out how to sort the strings by the area (eg: "Workroom etc..").
What I am trying to get is:
["1224 - Active - Breakroom",
"2365 - Active - Shop",
"1234 - Active - Workroom"]
The "Active" part will always be the same.
From what I have found online, I have to make a .sort() override method to sort it, but I cannot figure out what I need to change inside the override method.
Example for you
var items = [
{ name: "Edward", value: 21 },
{ name: "Sharpe", value: 37 },
{ name: "And", value: 45 },
{ name: "The", value: -12 },
{ name: "Magnetic" },
{ name: "Zeros", value: 37 }
];
items.sort(function (a, b) {
if (a.name > b.name)
return 1;
if (a.name < b.name)
return -1;
// a must be equal to b
return 0;
});
You can make 1 object to describe your data .
Example
data1 = { id : 12123, status:"Active", name:"Shop"}
You can implement your logic in sort().
Return 1 if a > b ;
Return -1 if a < b
Return 0 a == b.
Array will automatically order follow the return
Hope it'll help.
You can give the sort method a function that compares two items and returns the order:
yourArray.sort(function(item1, item2){
// compares item1 & item2 and returns:
// -1 if item1 is less than item2
// 0 if equal
// +1 if item1 is greater than item2
});
Example in your case :
yourArray.sort(function(item1, item2){
// don't forget to check for null/undefined values
var split1 = item1.split(' - ');
var split2 = item2.split(' - ');
return split1[2] < split2[2] ? -1 : (split1[2] > split2[2] ? 1 : 0);
});
see Array.prototype.sort()
You don't have to override anything, just pass .sort custom function that will do the sorting:
var rsortby = {
id : /^(\d+)/,
name : /(\w+)$/,
status : /-\s*(.+?)\s*-/,
};
var r = rsortby['name'];
[
'1234 - Active - Workroom',
'1224 - Active - Breakroom',
'2365 - Active - Shop',
].
sort(function(a, b) {
var ma = a.match(r)[1];
var mb = b.match(r)[1];
return (ma != mb) ? (ma < mb ? -1 : 1) : 0;
});
// ["1224 - Active - Breakroom", "2365 - Active - Shop", "1234 - Active - Workroom"]
//

Javascript array of objects will not sort, despite setting sort function

I have an array of objects, in which each contains several numerical values. Here is the layout of the object:
{
v: [],
cm: 0
}
This is the definition of the sort function:
registry.sort(function(a,b) {return (a.cm > b.cm) ? 1 : ((b.cm > a.cm) ? -1 : 0);} );
When I run the sort function, it does nothing whatsoever, just leaves the array the way it was. I am new to js, but as far as I can tell, everything should be working. Does anyone know what is wrong?
Thanks
EDIT: here is the smallest example I can extract
var registry = [];
registry.sort(function(a,b) {return (a.cm > b.cm) ? 1 : ((b.cm > a.cm) ? -1 : 0);} );
var draw = function() {
//various other function calls that add values to the registry array
registry[0] = {v:[0,0,0], cm:3}; //just to have something to use in the variable
registry[1] = {v:[0,0,0], cm:2};
debug(registry[0], registry[1]);
registry.sort();
debug(registry[0], registry[1]);
}
The sort() is not a configuration. When you call it, it does the sort. You can do this:
var comparator = function(a,b) {return (a.cm > b.cm) ? 1 : ((b.cm > a.cm) ? -1 : 0);}
for (var i = 0; i < regPos; i++) {
debug(registry[i], "eah");
}
registry.sort(comparator);
registry.reverse();
for (var i = 0; i < regPos; i++) {
debug(registry[i]);
}
Or simply
var comparator = function(a,b) {return a.cm - b.cm;}
The code below will sort the array "points" which has a similar structure... not sure if this is an exact match for your data though.
var points = [{v:[1,2,3],cm:40},{v:[2], cm:100},{v:[], cm:1},{cm:5,v:[]},{v:[3],cm:25},{cm:10}];
points.sort(function(a,b) {return (a.cm - b.cm);});
for (x in points) {
console.log(points[x]);
}
Are you sure the "cm" field is defined for every record in your array?

Categories

Resources