将有多个匹配项的项目移动到列表顶部
本文关键字:移动 项目 列表 顶部 | 更新日期: 2023-09-27 18:36:40
我有一个列表,可以包含多个人员记录:
result =people.Select(p => new PersonDetail
{
Involvement = p._Discriminator,
FullName = p.BuildFullName(),
DateOfBirth = p.DateOfBirth != null ? p.DateOfBirth.Value.ToShortDateString() : string.Empty,
Race = MappingExtensions.MergeCodeAndText(p.RaceCode, p.RaceText),
Sex = MappingExtensions.MergeCodeAndText(p.SexCode, p.SexText),
Height = p.Height,
Weight = p.Weight != null ? p.Weight.ToString() : string.Empty,
EyeColor = MappingExtensions.MergeCodeAndText(p.EyeColorCode, p.EyeColorText),
HairColor = MappingExtensions.MergeCodeAndText(p.HairColor1Code, p.HairColor1Text),
//...
}).ToList();
我想按参与类型(受害者、嫌疑人、证人)对此列表进行排序。
我使用Remove
和Insert
尝试了以下内容:
foreach (var i in result.Where(i => i.Involvement.ToLower() =="suspect"))
{
result.Remove(i);
result.Insert(0, i);
}
return result;
在第一个循环中,它按我预期的方式工作,但是在第二个循环中,我抛出了一个异常。我怀疑有一些递归正在进行或抛出异常,因为它不断找到我在第一次传递时提升的记录并且无法通过它。
我想执行一个循环而不是只执行一次传递,因为可能有多个记录被标记为可疑。我需要将所有这些提升到证人或受害者之上。其他参与与排序无关。
例:
Bob "suspect"
Jane"suspect"
Kenny "witness"
Joe "victim"
关于如何选择多个记录并确保它们位于列表顶部高于其他记录的任何建议?
感谢您的任何想法或建议
首先,您无法更改foreach中的结果集合。foreach 中使用的集合是不可变的,这里是 MSDN 链接,其中包含说明:foreach
您可以使用 OrderBy 对产品系列重新排序:
result = result.OrderBy(r => r.Involvement.ToLower() =="suspect" ? 0 : 1).ToList();
OrderBy 中的表达式会将"可疑"项提升到结果的顶部。
当前接受的答案只有在排序的列表只关心Suspect
位于列表顶部的优先级时才会成功,即
Kenny, Witness
Bob, Suspect
Joe, Victim
Jane, Suspect
换句话说,如果排序优先级还包括Witness
和Victim
,则接受的答案是正确的,因为见证人在顺序中已经优先于受害者;当使用接受的答案时,结果将正确为:
Bob, Suspect
Jane, Suspect
Kenny, Witness
Joe, Victim
但是,如果排序优先级必须包含"可疑"以外的字符串,则接受的答案将失败,即如果列表以
Jill, Victim
Kenny, Witness
Bob, Suspect
Joe, Victim
Jane, Suspect
然后结果将是:
Bob, Suspect
Jane, Suspect
Jill, Victim
Kenny, Witness
Joe, Victim
但是,正确的结果应该是(假设见证人优先于受害者):
Bob, Suspect
Jane, Suspect
Kenny, Witness
Jill, Victim
Joe, Victim
若要基于非 alpha 排序自定义排序,需要提供某种类型的 IComparer 或类似类型:
// Sample class with a name and involvement:
public class Detail
{
public string Name { get; set; }
public string Involvement { get; set; }
public Detail( string name, string involvement )
{
Name = name;
Involvement = involvement;
}
}
// implementation of IComparer that uses a custom alpha sort:
public class DetailComparer : IComparer<Detail>
{
static readonly List<string> Ordered = new List<string> { "suspect", "witness", "victim" };
public int Compare( Detail x, Detail y )
{
int i = Ordered.FindIndex( str => str.Equals( x.Involvement, StringComparison.OrdinalIgnoreCase ) );
int j = Ordered.FindIndex( str => str.Equals( y.Involvement, StringComparison.OrdinalIgnoreCase ) );
if( i > j ) return 1;
if( i < j ) return -1;
return 0;
}
}
然后可以通过提供比较器对列表进行排序:
var details = new List<Detail>
{
new Detail("Jill", "Victim"),
new Detail("Kenny", "Witness"),
new Detail("Bob", "Suspect"),
new Detail("Joe", "Victim"),
new Detail("Jane", "Suspect"),
};
details.Sort( new DetailComparer() );
通过提供自定义 IComparer,可以为每个"参与"声明任何优先级。