我需要以下结果。
所有数字都使用数字排序,所有字符串都使用字母数字排序。此外,数值应该列在字符串值之前:
例:在"i","9","89","0045","b","x"之前
在"9","0045","89","b","i","x" 之后
我当前的代码如下所示:(数字排序有效,但我的字符串分布在顶部和底部?! ->"b","x","9","0045","89","i")
public function compareFunction(obj1:Object, obj2:Object):int {
var id1:String = (obj1 as WdProblem).id;
var id2:String = (obj2 as WdProblem).id;
if(id1.replace(' ', '') == "n") {
var sdld:int = 0;
}
var num1:int = Number(id1);
var num2:int = Number(id2);
if(stringIsAValidNumber(id1) && stringIsAValidNumber(id2)) {
if(num1 == num2) {
return 0;
} else {
if(num1 > num2) {
return 1;
} else {
return -1;
}
}
} else if(!stringIsAValidNumber(id1) && !stringIsAValidNumber(id2)) {
return ObjectUtil.compare(id1, id2);
//return compareString(id1, id2);
} else if(!stringIsAValidNumber(id1) && stringIsAValidNumber(id2)) {
return 1;
} else if(stringIsAValidNumber(id1) && !stringIsAValidNumber(id2)) {
return -1;
}
return -1;
}
private function stringIsAValidNumber(s:String):Boolean {
return Boolean(s.match("[0-9]+(.[0-9][0-9]?)?"));
}
我的建议是将其分解为它的组成部分,特别是如果您有这样的具有 1 个或多个优先级排序的场景。关键是只有在第一个排序返回它们相等时才进入下一个排序。
对于您的情况,我会构建 2 种排序,一种用于数字,另一种用于字母数字,然后您的主排序可以通过调用子排序来优先考虑这些排序。
例如,我有类似的东西:
private function sort2DimensionsByIncomeVsTime(a:OLAPSummaryCategory, b:OLAPSummaryCategory, fields:Array = null):int
{
var sort:OLAPSort = new OLAPSort();
var incomeSort:int = sort.sortIncome(a, b);
var nameSort:int = sort.sortName(a, b);
var yrSort:int = sort.sortYear(a, b);
var moSort:int = sort.sortMonth(a, b);
if (incomeSort == 0)
{
if (nameSort == 0)
{
if (yrSort == 0)
{
//trace(a.name, a.year, a.month, 'vs:', b.name, b.year, b.month, 'month sort:', moSort);
return moSort;
}
else return yrSort;
}
else return nameSort;
}
else return incomeSort;
}
我使用以下排序函数进行字母数字排序:
<?xml version="1.0" encoding="utf-8"?>
<s:Application
creationComplete="onCC()"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.utils.ObjectUtil;
import mx.utils.StringUtil;
import spark.collections.Sort;
import spark.collections.SortField;
public function onCC():void
{
var acAlphaNumericString:ArrayCollection = new ArrayCollection();
acAlphaNumericString.addItem({ name: "NUM10071" });
acAlphaNumericString.addItem({ name: "NUM9999" });
acAlphaNumericString.addItem({ name: "9997" });
acAlphaNumericString.addItem({ name: "9998" });
acAlphaNumericString.addItem({ name: "9996" });
acAlphaNumericString.addItem({ name: "9996F" });
acAlphaNumericString.addItem({ name: "i" });
acAlphaNumericString.addItem({ name: "9" });
acAlphaNumericString.addItem({ name: "89" });
acAlphaNumericString.addItem({ name: "0045" });
acAlphaNumericString.addItem({ name: "b" });
acAlphaNumericString.addItem({ name: "x" });
var sf:SortField = new SortField("name");
sf.compareFunction = function(o1:Object, o2:Object):int
{
return compare(o1.name, o2.name);
}
var sort:Sort = new Sort();
sort.fields = [ sf ];
acAlphaNumericString.sort = sort;
acAlphaNumericString.refresh();
for each (var o:Object in acAlphaNumericString)
trace(o.name);
}
public static function compare(firstString:String, secondString:String):int
{
if (secondString == null || firstString == null)
return 0;
var lengthFirstStr:int = firstString.length;
var lengthSecondStr:int = secondString.length;
var index1:int = 0;
var index2:int = 0;
while (index1 < lengthFirstStr && index2 < lengthSecondStr)
{
var ch1:String = firstString.charAt(index1);
var ch2:String = secondString.charAt(index2);
var space1:String = "";
var space2:String = "";
do
{
space1 += ch1;
index1++;
if (index1 < lengthFirstStr)
ch1 = firstString.charAt(index1);
else
break;
} while (isDigit(ch1) == isDigit(space1.charAt(0)));
do
{
space2 += ch2;
index2++;
if (index2 < lengthSecondStr)
ch2 = secondString.charAt(index2);
else
break;
} while (isDigit(ch2) == isDigit(space2.charAt(0)));
var str1:String = new String(space1);
var str2:String = new String(space2);
var result:int;
if (isDigit(space1.charAt(0)) && isDigit(space2.charAt(0)))
{
var firstNumberToCompare:int = parseInt(StringUtil.trim(str1));
var secondNumberToCompare:int = parseInt(StringUtil.trim(str2));
result = ObjectUtil.numericCompare(firstNumberToCompare, secondNumberToCompare);
}
else
result = ObjectUtil.compare(str1, str2);
if (result != 0)
return result;
}
return lengthFirstStr - lengthSecondStr;
function isDigit(ch:String):Boolean
{
var code:int = ch.charCodeAt(0);
return code >= 48 && code <= 57;
}
}
]]>
</fx:Script>
</s:Application>