LINQ和区分大小写
我有一个LINQ查询:LINQ和区分大小写,linq,sorting,linq-to-objects,case-sensitive,Linq,Sorting,Linq To Objects,Case Sensitive,我有一个LINQ查询: TempRecordList = new ArrayList(TempRecordList.Cast<string>().OrderBy(s => s.Substring(9, 30)).ToArray()); TempRecordList=newArrayList(TempRecordList.Cast().OrderBy(s=>s.Substring(9,30)).ToArray()); 它工作得很好,以一种精确的方式执行排序,但与我想要的略有不
TempRecordList = new ArrayList(TempRecordList.Cast<string>().OrderBy(s => s.Substring(9, 30)).ToArray());
TempRecordList=newArrayList(TempRecordList.Cast().OrderBy(s=>s.Substring(9,30)).ToArray());
它工作得很好,以一种精确的方式执行排序,但与我想要的略有不同。在查询结果中,我看到如下内容:
彼得·帕尔姆·鲍特
帕默·约翰逊,肖恩
而我真正需要的是让名字按如下顺序排列:
帕默·约翰逊,肖恩彼得·鲍特·帕尔姆 基本上,我希望将“-”字符视为低于该字符,以便包含它的名称稍后在升序搜索中显示 这里是另一个例子。我得到: Dias,Reginald
迪布拉克利,安东 而不是: 迪布拉克利,安东
迪亚斯,雷金纳德 正如您所看到的,同样,由于大写字母“B”的处理方式,顺序被切换 所以我的问题是,我需要在我的LINQ查询中更改什么才能使它按照我指定的顺序返回结果。任何反馈都将得到极大的重视 顺便说一句,我试着使用s.Substring(9,30).ToLower(),但是没有用 谢谢大家!
OrderBy()
以升序返回结果
e
位于h
之前,因此第一个结果(请记住,您是在一个子串上进行比较,该子串以第9位的字符开头…而不是字符串的开头)和i
位于y
之前,因此是第二个结果。区分大小写与此无关
如果希望结果按降序排列,则应使用OrderByDescending()
:
TempRecordList.Cast
.OrderByDescending(s=>s.Substring(9,30)).ToArray();
要自定义排序顺序,您需要创建一个实现IComparer
接口的比较器类。OrderBy()
方法将比较器作为第二个参数
internal sealed class NameComparer : IComparer<string> {
private static readonly NameComparer DefaultInstance = new NameComparer();
static NameComparer() { }
private NameComparer() { }
public static NameComparer Default {
get { return DefaultInstance; }
}
public int Compare(string x, string y) {
int length = Math.Min(x.Length, y.Length);
for (int i = 0; i < length; ++i) {
if (x[i] == y[i]) continue;
if (x[i] == '-') return 1;
if (y[i] == '-') return -1;
return x[i].CompareTo(y[i]);
}
return x.Length - y.Length;
}
}
您可能只需要实现一个自定义IComparer对象,该对象将为特殊、大写和小写字符提供自定义优先级
如前所述,
OrderBy()
方法将比较器作为第二个参数
internal sealed class NameComparer : IComparer<string> {
private static readonly NameComparer DefaultInstance = new NameComparer();
static NameComparer() { }
private NameComparer() { }
public static NameComparer Default {
get { return DefaultInstance; }
}
public int Compare(string x, string y) {
int length = Math.Min(x.Length, y.Length);
for (int i = 0; i < length; ++i) {
if (x[i] == y[i]) continue;
if (x[i] == '-') return 1;
if (y[i] == '-') return -1;
return x[i].CompareTo(y[i]);
}
return x.Length - y.Length;
}
}
对于字符串,您不必实现IComparer
。您可以使用System.StringComparer.CurrentCulture
(或System.StringComparer
中的另一个)
但是,在您的实际情况中,没有内置的比较器可以处理字母排序顺序之后的
-
。但是我确实希望结果以升序返回。我的问题可能没有说得很清楚,但所有的结果都是相对而言的。只是上面的名字不是我想要的。我想,我真正想做的是改变升序排序的执行方式。是否有一种文化或我可以指定的东西?谢谢@冈佐奈特-我想我错过了你想要实现的目标。您是基于原始的子字符串进行排序(这是正确的),但您不希望以这种方式显示它们。如果是这样的话,那么为什么要首先根据子字符串对它们进行排序呢?不要让这一部分迷惑了你。整个项目是Cobol到C#的转换,显然Cobol中升序排序的规则有些不同。我提到的首选顺序直接来自Cobol输出。我的结果99.5%正确,但2200个名字中有15个排序错误。我上面给出的示例几乎涵盖了两个输出的不兼容范围。因此,我正在显示结果,我只是试图使它们完全相同。这听起来似乎可行,但我不确定我是否能够自己编写一个类来执行这些比较。@mgronber-非常感谢!我将尝试此代码并返回结果。我似乎对以下行有问题:[b]内部密封类名称比较程序:IComparer[b]。我得到:错误1非泛型类型“System.Collections.IComparer”不能与类型参数一起使用。不过我可能知道怎么修。我将尝试其他方法并返回。这一行还有另一个问题:new ArrayList(TempRecordList.OrderBy(s=>s.Substring(9,30,NameComparer.Default)).ToArray();我发现IOrderedNumeral的类型无法从其用法中推断出来,请尝试显式指定它。您使用ArrayList
而不是List
,有什么具体原因吗?实际上,我尝试过这样做。下面是我想到的:公共类ArrayComparer:IComparer{public int Compare(object x,object y){string left=x.ToString();string right=y.ToString();string lhs=left.Substring(9,30);string rhs=right.Substring(9,30);返回lhs.CompareTo(rhs);}}但这只做常规比较。我不知道如何更改它,以便它为特殊、大写和小写字符提供自定义优先级。
var names = new[] {
"Palmer-Johnson, Sean",
"Palm-Bouter, Peter",
"Dias, Reginald",
"DiBlackley, Anton",
};
var sorted = names.OrderBy(name => name, NameComparer.Default).ToList();
// sorted:
// [0]: "DiBlackley, Anton"
// [1]: "Dias, Reginald"
// [2]: "Palmer-Johnson, Sean"
// [3]: "Palm-Bouter, Peter"