Created
March 27, 2011 08:13
-
-
Save think49/889027 to your computer and use it in GitHub Desktop.
natural-language.js : 自然言語アルゴリズムで配列やノードリストをソートする
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* natural-language.js | |
* Array is sorted by natural language algorithm. | |
* | |
* @version 0.9 | |
* @author think49 | |
* @url https://github.com/think49 | |
* @license http://www.opensource.org/licenses/mit-license.php (The MIT License) | |
* @see <a href="http://sourcefrog.net/projects/natsort/">Natural Order String Comparison</a> | |
*/ | |
'use strict'; | |
var NaturalLanguage = (function () { | |
'use strict'; | |
function NaturalLanguage () { | |
if (!(this instanceof NaturalLanguage)) { | |
return new NaturalLanguage(); | |
} | |
} | |
(function (sort, slice) { | |
/** | |
* included is-object.js | |
* | |
* @version 1.0.2 | |
* @author think49 | |
* @url https://gist.github.com/887049 | |
*/ | |
function isObject (value) { | |
var result; | |
if (value === null) { | |
return false; | |
} | |
switch (typeof value) { | |
case 'undefined': | |
case 'boolean': | |
case 'number': | |
case 'string': | |
result = false; | |
break; | |
case 'object': // Object (native and does not implement [[Call]]) | |
case 'function': // Object (native or host and does implement [[Call]]) | |
default: // Object (host and does not implement [[Call]]) | |
result = true; | |
break; | |
} | |
return result; | |
} | |
function natCompare (string1, string2) { | |
var _String, _Number, result, charCode1, charCode2, isNumber1, isNumber2, isPeriod1, isPeriod2, number1, number2, numCheck, i, l; | |
_String = String; | |
string1 = _String(string1); | |
string2 = _String(string2); | |
if (string1.length > string2.length) { | |
l = string1.length; | |
result = 1; | |
} else if (string1.length < string2.length) { | |
l = string2.length; | |
result = -1; | |
} else { | |
l = string1.length; | |
result = 0; | |
} | |
string1 = string1.replace(/\s+/g, '').toLowerCase(); | |
string2 = string2.replace(/\s+/g, '').toLowerCase(); | |
if (string1 === string2) { | |
return 0; | |
} | |
_Number = Number; | |
number1 = ''; | |
number2 = ''; | |
for (i = 0; i < l; i++) { | |
charCode1 = string1.charCodeAt(i); | |
charCode2 = string2.charCodeAt(i); | |
isNumber1 = charCode1 > 47 && charCode1 < 58; | |
isNumber2 = charCode2 > 47 && charCode2 < 58; | |
isPeriod1 = charCode1 === 46 && number1.indexOf('.') === -1; | |
isPeriod2 = charCode2 === 46 && number2.indexOf('.') === -1; | |
if (numCheck && (isNumber1 || isNumber2 || isPeriod1 || isPeriod2) || isNumber1 && isNumber2) { | |
if (isNumber1 || isPeriod1) { | |
number1 += string1.charAt(i); | |
} | |
if (isNumber2 || isPeriod2) { | |
number2 += string2.charAt(i); | |
} | |
numCheck = true; | |
} else { | |
if (number1.length && number2.length) { | |
number1 = _Number(number1); | |
number2 = _Number(number2); | |
if (number1 > number2) { | |
return 1; | |
} else if (number1 < number2) { | |
return -1; | |
} | |
number1 = ''; | |
number2 = ''; | |
numCheck = false; | |
} | |
if (charCode1 > charCode2) { | |
return 1; | |
} else if (charCode1 < charCode2) { | |
return -1; | |
} | |
} | |
} | |
if (number1.length && number2.length) { | |
number1 = _Number(number1); | |
number2 = _Number(number2); | |
if (number1 > number2) { | |
return 1; | |
} else if (number1 < number2) { | |
return -1; | |
} | |
} | |
return result; | |
} | |
function createNatCompareWithCallback (callbackfn) { | |
return function (value1, value2) { | |
return natCompare(callbackfn(value1), callbackfn(value2)); | |
}; | |
} | |
this.sortFromArray = function sortFromArray (array/*, callbackfn*/) { | |
if (arguments.length > 1 && typeof arguments[1] === 'function') { | |
return sort.call(array, createNatCompareWithCallback(arguments[1])); | |
} | |
return sort.call(array, natCompare); | |
}; | |
this.sortFromNodes = function sortFromNodes (nodes, callbackfn) { | |
var parentNode, node1, node2, i, len, incomplete; | |
if (!isObject(nodes)) { | |
throw new TypeError(nodes + ' is not a object'); | |
} | |
if (typeof callbackfn !== 'function') { | |
throw new TypeError(callbackfn + ' is not a function'); | |
} | |
node1 = nodes[0]; | |
if (!node1) { | |
return; | |
} | |
parentNode = node1.parentNode; | |
if (!parentNode) { | |
return; | |
} | |
incomplete = true; | |
console.log('sortFromNodes'); | |
console.log(nodes.length); | |
while (incomplete) { | |
incomplete = false; | |
for (i = 1, len = nodes.length; i < len; ++i) { | |
node1 = nodes[i - 1]; | |
node2 = nodes[i]; | |
if (natCompare(callbackfn(node1), callbackfn(node2)) === 1) { | |
parentNode.insertBefore(node2, node1); | |
len = nodes.length; | |
incomplete = true; | |
} | |
} | |
} | |
console.log(nodes.length); | |
return nodes; | |
}; | |
}).call(NaturalLanguage.prototype, Array.prototype.sort, Array.prototype.slice); | |
return NaturalLanguage; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment