C# IOrderComparer唯一订购情况
我正在尝试以一种独特的方式订购混合字符串,我想知道是否有其他人这样做过。我已经找到了几篇关于使用IOrderConparer的文章,但没有找到解决我的特殊排序问题的方法 我有以下资料: 1017、650、650C、650B、W323、10、20、1000、W1000 我需要按如下顺序订购: 10、20、650、650B、650C、1000、1017、W323、W1000C# IOrderComparer唯一订购情况,c#,linq,C#,Linq,我正在尝试以一种独特的方式订购混合字符串,我想知道是否有其他人这样做过。我已经找到了几篇关于使用IOrderConparer的文章,但没有找到解决我的特殊排序问题的方法 我有以下资料: 1017、650、650C、650B、W323、10、20、1000、W1000 我需要按如下顺序订购: 10、20、650、650B、650C、1000、1017、W323、W1000 任何帮助都将不胜感激。谢谢。使用strmplogicalw执行比较: [DllImport("shlwapi.dll", Ch
任何帮助都将不胜感激。谢谢。使用strmplogicalw执行比较:
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern int StrCmpLogicalW(string x, string y);
这将进行逻辑(考虑数字)字符串比较,而不是基于标准字符串的比较,这将为您提供所需的结果。稍长一点,但所有托管代码
public class LogicalSorter : IComparer
{
public int Compare(object a, object b)
{
var first = Regex.Split((string)a,"([0-9]+)").Where(s => s != "").ToArray();
var second = Regex.Split((string)b,"([0-9]+)").Where(s => s != "").ToArray();
var endIdx = Math.Min(first.Count(), second.Count());
for (var i = 0; i < endIdx; i++)
{
var part1 = first.ElementAt(i);
var part2 = second.ElementAt(i);
if (part1.All(char.IsDigit) && part2.All(char.IsDigit) && part1 != part2)
{
return int.Parse(part1).CompareTo(int.Parse(part2));
}
if (part1 != part2) return part1.CompareTo(part2);
}
return first.Count().CompareTo(second.Count());
}
}
或使用Mrinal建议的仿制药(首选)
公共类逻辑排序器:IComparer
{
公共整数比较(字符串a、字符串b)
{
var first=Regex.Split(a,“([0-9]+)”),其中(s=>s!=”).ToArray();
var second=Regex.Split(b,“([0-9]+)”),其中(s=>s!=”).ToArray();
var endIdx=Math.Min(first.Count(),second.Count());
对于(变量i=0;i
优化的托管代码示例(用于速度而非外观),在regex版本中执行
public class LogicalSorter : IComparer<String>
{
public int Compare(String a, String b)
{
var aLength = a.Length;
var bLength = b.Length;
var aIdx = 0;
var bIdx = 0;
int aPartLen;
int bPartLen;
int aPartEndIndex;
int bPartEndIndex;
bool aIsString;
bool bIsString;
// Examine both strings on character level, keep track of where
// we are in each string since lengths might differ
while (aIdx < aLength && bIdx < bLength)
{
// If both strings contain digit at current index
// compare numbers
if (char.IsDigit(a[aIdx]) && char.IsDigit(b[bIdx]))
{
// Get longest consecutive list of digits from each string
aPartEndIndex = aIdx;
while (aPartEndIndex < aLength && char.IsDigit(a[aPartEndIndex])) { aPartEndIndex++; }
bPartEndIndex = bIdx;
while (bPartEndIndex < bLength && char.IsDigit(b[bPartEndIndex])) { bPartEndIndex++; }
aPartLen = aPartEndIndex - aIdx;
bPartLen = bPartEndIndex - bIdx;
// Compare lengths (longest number is greater)
if (aPartLen != bPartLen) return aPartLen < bPartLen ? -1 : 1;
// Same length numbers, compare chars until not same or end
while (aIdx < aPartEndIndex && a[aIdx] == b[bIdx])
{
aIdx++;
bIdx++;
}
// If not at end compare last characters that were not same
if(aIdx != aPartEndIndex)
return a[aIdx] < b[bIdx] ? -1 : 1;
}
else
{
// Comparing string vs number or string vs string
aIsString = char.IsLetter(a[aIdx]);
bIsString = char.IsLetter(b[bIdx]);
// if not 2 strings, number is always first
if (aIsString != bIsString) return aIsString ? 1 : -1;
// Get longest consecutive list of letters from each string
aPartEndIndex = aIdx;
while (aPartEndIndex < aLength && (char.IsLetter(a[aPartEndIndex]) == aIsString))
{
aPartEndIndex++;
}
bPartEndIndex = bIdx;
while (bPartEndIndex < bLength && (char.IsLetter(b[bPartEndIndex]) == bIsString))
{
bPartEndIndex++;
}
// Compare chars until not same or end
while (aIdx < aPartEndIndex && bIdx < bPartEndIndex && a[aIdx] == b[bIdx])
{
aIdx++;
bIdx++;
}
// if not at end compare last letters found
if ((aIdx != aPartEndIndex) || (bIdx != bPartEndIndex))
return a[aIdx] < b[bIdx] ? -1 : 1;
}
}
// Use length as tie breaker
return aLength < bLength ? -1 : 1;
}
}
公共类逻辑排序器:IComparer
{
公共整数比较(字符串a、字符串b)
{
var aLength=a.长度;
var bLength=b.长度;
var-aIdx=0;
var-bIdx=0;
国际公寓;
int bPartLen;
国际公寓指数;
int bPartEndIndex;
布尔爱斯林;
布尔比斯林;
//在字符级别检查两个字符串,跟踪其中的位置
//因为长度可能不同,所以我们在每个字符串中
而(aIdx
订购背后的逻辑是什么?是的,只是你没有阅读问题。他在询问分拣顺序。他需要的是逻辑排序,而不是字符串排序。在.Net范例中,自定义IComparer是更好的选择,而不是使用非托管代码的PInvoke。还可以让我们了解PInvoke是您正在投影的其他人的代码,首先创建自己的版本,然后再开始性能测试bandwagon@Cyberdrew这是一个纯托管代码的解决方案,它会很快让你大吃一惊!工作起来很有魅力!为什么PInvoke用于逻辑字符串比较,应该有一种管理方式来实现itLOL。。。嗯,pinvoke版本比您的托管版本快10倍以上,所以我想我会使用pinvoke版本,因为我关心性能:)。在您的梦中,pinvoke将击败托管代码,您可能希望检索您的语句,否则很明显您对.Net framework及其工作方式一无所知。不要去宣称它,因为你所看到的并不是最有效的IComparer代码。同样,当你发表这样的声明时,是否愿意在我的梦中发布一些数据来支持你的版本?你真的读过他写的代码吗?李瑞杰
public class LogicalSorter : IComparer<String>
{
public int Compare(String a, String b)
{
var first = Regex.Split(a, "([0-9]+)").Where(s => s != "").ToArray();
var second = Regex.Split(b, "([0-9]+)").Where(s => s != "").ToArray();
var endIdx = Math.Min(first.Count(), second.Count());
for (var i = 0; i < endIdx; i++)
{
var part1 = first.ElementAt(i);
var part2 = second.ElementAt(i);
if (part1.All(char.IsDigit) && part2.All(char.IsDigit) && part1 != part2)
{
return int.Parse(part1).CompareTo(int.Parse(part2));
}
if (part1 != part2) return part1.CompareTo(part2);
}
return first.Count().CompareTo(second.Count());
}
}
public class LogicalSorter : IComparer<String>
{
public int Compare(String a, String b)
{
var aLength = a.Length;
var bLength = b.Length;
var aIdx = 0;
var bIdx = 0;
int aPartLen;
int bPartLen;
int aPartEndIndex;
int bPartEndIndex;
bool aIsString;
bool bIsString;
// Examine both strings on character level, keep track of where
// we are in each string since lengths might differ
while (aIdx < aLength && bIdx < bLength)
{
// If both strings contain digit at current index
// compare numbers
if (char.IsDigit(a[aIdx]) && char.IsDigit(b[bIdx]))
{
// Get longest consecutive list of digits from each string
aPartEndIndex = aIdx;
while (aPartEndIndex < aLength && char.IsDigit(a[aPartEndIndex])) { aPartEndIndex++; }
bPartEndIndex = bIdx;
while (bPartEndIndex < bLength && char.IsDigit(b[bPartEndIndex])) { bPartEndIndex++; }
aPartLen = aPartEndIndex - aIdx;
bPartLen = bPartEndIndex - bIdx;
// Compare lengths (longest number is greater)
if (aPartLen != bPartLen) return aPartLen < bPartLen ? -1 : 1;
// Same length numbers, compare chars until not same or end
while (aIdx < aPartEndIndex && a[aIdx] == b[bIdx])
{
aIdx++;
bIdx++;
}
// If not at end compare last characters that were not same
if(aIdx != aPartEndIndex)
return a[aIdx] < b[bIdx] ? -1 : 1;
}
else
{
// Comparing string vs number or string vs string
aIsString = char.IsLetter(a[aIdx]);
bIsString = char.IsLetter(b[bIdx]);
// if not 2 strings, number is always first
if (aIsString != bIsString) return aIsString ? 1 : -1;
// Get longest consecutive list of letters from each string
aPartEndIndex = aIdx;
while (aPartEndIndex < aLength && (char.IsLetter(a[aPartEndIndex]) == aIsString))
{
aPartEndIndex++;
}
bPartEndIndex = bIdx;
while (bPartEndIndex < bLength && (char.IsLetter(b[bPartEndIndex]) == bIsString))
{
bPartEndIndex++;
}
// Compare chars until not same or end
while (aIdx < aPartEndIndex && bIdx < bPartEndIndex && a[aIdx] == b[bIdx])
{
aIdx++;
bIdx++;
}
// if not at end compare last letters found
if ((aIdx != aPartEndIndex) || (bIdx != bPartEndIndex))
return a[aIdx] < b[bIdx] ? -1 : 1;
}
}
// Use length as tie breaker
return aLength < bLength ? -1 : 1;
}
}