我有一个无序列表,看起来像这样:
1
2.2
1.1.1
3
当我对列表进行排序时,1.1.1变得大于3和2.2,而2.2变得大于3.
这是因为Double.Parse删除了点并使其成为整数。
这是我用来排序的方法:
public class CompareCategory: IComparer<Category>
{
public int Compare(Category c1, Category c2)
{
Double cat1 = Double.Parse(c1.prefix);
Double cat2 = Double.Parse(c2.prefix);
if (cat1 > cat2)
return 1;
else if (cat1 < cat2)
return -1;
else
return 0;
}
}
我该如何解决这个问题? 感谢
答案 0 :(得分:10)
这些版本是偶然的吗?你能用the Version
class吗?它按照您的需要对每个部件进行排序,尽管它最多只能处理4个部件。我不建议像你一样解析成数值。
它有一个IComparable
接口。假设您的输入是字符串,这是一个示例:
public class CompareCategory: IComparer<Category>
{
public int Compare(Category c1, Category c2)
{
var cat1 = new Version(c1.prefix);
var cat2 = new Version(c2.prefix);
if (cat1 > cat2)
return 1;
else if (cat1 < cat2)
return -1;
else
return 0;
}
}
如果你需要超过4个“部分”的东西,我想我会创建一个比较器,它在点处分割字符串,然后将每个元素解析为整数并用数字进行比较。请务必考虑1.002.3和1.3.3之类的情况(您希望排序顺序是什么?)。
更新,这是我的意思的样本。经过轻微测试:
public class CategoryComparer : Comparer<Category>
{
public override int Compare(Category x, Category y)
{
var xParts = x.prefix.Split(new[] { '.' });
var yParts = y.prefix.Split(new[] { '.' });
int index = 0;
while (true)
{
bool xHasValue = xParts.Length > index;
bool yHasValue = yParts.Length > index;
if (xHasValue && !yHasValue)
return 1; // x bigger
if (!xHasValue && yHasValue)
return -1; // y bigger
if (!xHasValue && !yHasValue)
return 0; // no more values -- same
var xValue = decimal.Parse("." + xParts[index]);
var yValue = decimal.Parse("." + yParts[index]);
if (xValue > yValue)
return 1; // x bigger
if (xValue < yValue)
return -1; // y bigger
index++;
}
}
}
public static void Main()
{
var categories = new List<Category>()
{
new Category { prefix = "1" },
new Category { prefix = "2.2" },
new Category { prefix = "1.1.1" },
new Category { prefix = "1.1.1" },
new Category { prefix = "1.001.1" },
new Category { prefix = "3" },
};
categories.Sort(new CategoryComparer());
foreach (var category in categories)
Console.WriteLine(category.prefix);
}
输出:
1
1.001.1
1.1.1
1.1.1
2.2
3
答案 1 :(得分:1)
public class CodeComparer : IComparer<string>
{
public int Compare(string x, string y)
{
var xParts = x.Split(new char[] { '.' });
var yParts = y.Split(new char[] { '.' });
var partsLength = Math.Max(xParts.Length, yParts.Length);
if (partsLength > 0)
{
for (var i = 0; i < partsLength; i++)
{
if (xParts.Length <= i) return -1;// 4.2 < 4.2.x
if (yParts.Length <= i) return 1;
var xPart = xParts[i];
var yPart = yParts[i];
if (string.IsNullOrEmpty(xPart)) xPart = "0";// 5..2->5.0.2
if (string.IsNullOrEmpty(yPart)) yPart = "0";
if (!int.TryParse(xPart, out var xInt) || !int.TryParse(yPart, out var yInt))
{
// 3.a.45 compare part as string
var abcCompare = xPart.CompareTo(yPart);
if (abcCompare != 0)
return abcCompare;
continue;
}
if (xInt != yInt) return xInt < yInt ? -1 : 1;
}
return 0;
}
// compare as string
return x.CompareTo(y);
}
}
答案 2 :(得分:0)
也许你可以对它进行字符串比较?
答案 3 :(得分:0)
我很惊讶Double.Parse不会对那些小数位多的数字抛出异常。
你真的需要写一些关于如何比较这些字符串的规则。
我会在点字符上使用String.Split()拆分字符串,然后遍历创建的两个列表,并且只要其中一个级别包含比另一个更低或更高的数字,或者如果你用完了其中一个列表中的项目然后您将根据需要返回1或-1。如果你在循环的同一次迭代中到达两个列表的末尾,那么它们是相同的并返回0.
我会写代码,但我没有VS在我面前。