function naturalSort(stringArray) {
var arr = stringArray;
// ...
return arr.sort(compareStrings) //
}
function compareStrings(str1, str2) {
//
var compare = function (a, b) {
return (a < b) ? -1 : (a > b) ? 1 : 0;
};
// ; splitString()
var parts1 = splitString(str1);
var parts2 = splitString(str2);
//
var minLength = Math.min(parts1.length, parts2.length);
for ( var i = 0; i < minLength; i++) {
//
}
//
// , "", , ""
return compare(parts1.length, parts2.length);
}
function splitString(str) {
var from = 0; // slice()
var index = 0; //
var count = 0; //
var splitter = {}; //
//
splitter.count = function () {
return count;
}
//
splitter.next = function () {
// - null
if (index === str.length) {
return null ;
}
//
while (++index) {
var currentIsDigit = isDigit(str.charAt(index - 1)); // isDigit()
var nextChar = str.charAt(index);
var currentIsLast = (index === str.length);
// - ,
// ( / )
var isBorder = currentIsLast ||
xor(currentIsDigit, isDigit(nextChar)); // xor()
if (isBorder) {
var part = str.slice(from, index);
from = index;
count++;
return {
IsNumber: currentIsDigit,
Value: currentIsDigit ? Number(part) : part
};
} // end if
} // end while
}; // end next()
return splitter;
}
function xor(a, b) {
return a ? !b : b;
}
function isDigit(chr) {
var charCode = function (ch) {
return ch.charCodeAt(0);
};
var code = charCode(chr);
return (code >= charCode( '0' )) && (code <= charCode( '9' ));
}
function compareStrings(str1, str2) {
//
var compare = function (a, b) {
return (a < b) ? -1 : (a > b) ? 1 : 0;
};
//
var splitter1 = splitString(str1);
var splitter2 = splitString(str2);
//
while ( true ) {
var first = splitter1.next();
var second = splitter2.next();
// ...
if ( null !== first && null !== second) {
// ( )
if (xor(first.IsNumber, second.IsNumber)) {
// ""
return first.IsNumber ? -1 : 1;
//
} else {
var comp = compare(first.Value, second.Value);
if (comp != 0) {
return comp;
}
} // end if
// ... - ""
} else {
return compare(splitter1.count(), splitter2.count());
}
} // end while
}
function naturalSort(stringArray) {
// ""
var xor = function (a, b) {
return a ? !b : b;
};
// ,
var isDigit = function (chr) {
var charCode = function (ch) {
return ch.charCodeAt(0);
};
var code = charCode(chr);
return (code >= charCode( '0' )) && (code <= charCode( '9' ));
};
//
var splitString = function (str) {
var from = 0; // slice()
var index = 0; //
var count = 0; //
var splitter = {}; //
//
splitter.count = function () {
return count;
}
//
splitter.next = function () {
// - null
if (index === str.length) {
return null ;
}
//
while (++index) {
var currentIsDigit = isDigit(str.charAt(index - 1));
var nextChar = str.charAt(index);
var currentIsLast = (index === str.length);
// - ,
// ( / )
var isBorder = currentIsLast ||
xor(currentIsDigit, isDigit(nextChar));
if (isBorder) {
var part = str.slice(from, index);
from = index;
count++;
return {
IsNumber: currentIsDigit,
Value: currentIsDigit ? Number(part) : part
};
} // end if
} // end while
}; // end next()
return splitter;
};
// ""
var compareStrings = function (str1, str2) {
//
var compare = function (a, b) {
return (a < b) ? -1 : (a > b) ? 1 : 0;
};
//
var splitter1 = splitString(str1);
var splitter2 = splitString(str2);
//
while ( true ) {
var first = splitter1.next();
var second = splitter2.next();
// ...
if ( null !== first && null !== second) {
// ( )
if (xor(first.IsNumber, second.IsNumber)) {
// ""
return first.IsNumber ? -1 : 1;
//
} else {
var comp = compare(first.Value, second.Value);
if (comp != 0) {
return comp;
}
} // end if
// ... - ""
} else {
return compare(splitter1.count(), splitter2.count());
}
} // end while
}
//
var arr = stringArray;
return arr.sort(compareStrings);
}
function naturalSort(array, extractor) {
"use strict" ;
//
var splitters = array.map(makeSplitter);
//
var sorted = splitters.sort(compareSplitters);
//
return sorted.map( function (splitter) {
return splitter.item;
});
//
function makeSplitter(item) {
return new Splitter(item);
}
//
// ""
function Splitter(item) {
var index = 0; //
var from = 0; //
var parts = []; //
var completed = false ; //
//
this .item = item;
// -
var key = ( typeof (extractor) === 'function' ) ?
extractor(item) :
item;
this .key = key;
//
this .count = function () {
return parts.length;
};
// ( parts[])
this .part = function (i) {
while (parts.length <= i && !completed) {
next(); //
}
return (i < parts.length) ? parts[i] : null ;
};
//
function next() {
//
if (index < key.length) {
//
while (++index) {
var currentIsDigit = isDigit(key.charAt(index - 1));
var nextChar = key.charAt(index);
var currentIsLast = (index === key.length);
// - ,
// ( / )
var isBorder = currentIsLast ||
xor(currentIsDigit, isDigit(nextChar));
if (isBorder) {
// parts[]
var partStr = key.slice(from, index);
parts.push( new Part(partStr, currentIsDigit));
from = index;
break ;
} // end if
} // end while
//
} else {
completed = true ;
} // end if
} // end next
//
function Part(text, isNumber) {
this .isNumber = isNumber;
this .value = isNumber ? Number(text) : text;
}
}
//
function compareSplitters(sp1, sp2) {
var i = 0;
do {
var first = sp1.part(i);
var second = sp2.part(i);
// ...
if ( null !== first && null !== second) {
// ( )
if (xor(first.isNumber, second.isNumber)) {
// ""
return first.isNumber ? -1 : 1;
//
} else {
var comp = compare(first.value, second.value);
if (comp != 0) {
return comp;
}
} // end if
// ... - ""
} else {
return compare(sp1.count(), sp2.count());
}
} while (++i);
//
function compare(a, b) {
return (a < b) ? -1 : (a > b) ? 1 : 0;
};
};
// ""
function xor(a, b) {
return a ? !b : b;
};
// :
function isDigit(chr) {
var code = charCode(chr);
return (code >= charCode( '0' )) && (code <= charCode( '9' ));
function charCode(ch) {
return ch.charCodeAt(0);
};
};
}
function thanks() {
alert( 'C PoiSoN Source Code Highlighter' );
};
* This source code was highlighted with Source Code Highlighter .
Source: https://habr.com/ru/post/127943/