我的模特是:
class Person
{
public int Id {get; set; }
public string Name {get; set; }
}
我有两个系列。我想像toBeSortedList
那样排序etalonList
:
List<Person> etalonList = new List<Person>()
{
new Person() { Id=10, Name="Jon"},
new Person() { Id=4, Name="Ben"},
new Person() { Id=11, Name="Magnus"},
new Person() { Id=8, Name="Joseph"},
};
List<Person> toBeSortedList = new List<Person>()
{
new Person() { Id=11, Name="Magnus"},
new Person() { Id=4, Name="Ben"},
new Person() { Id=10, Name="Jon"},
new Person() { Id=8, Name="Joseph"},
};
我试过了:
var orderedByIdList = tobeSortedList.OrderBy(x => etalonList.IndexOf(x.Id));
但我遇到了这样的错误:
无法转换为&#39; int&#39;到&#39; SOConsoleApplication.Person&#39;
也许你还有其他建议?
答案 0 :(得分:3)
我首先要从etalonList
创建一个字典,以加快排序速度:
int index;
var etalonDictionary = etalonList.ToDictionary(k => k.Id, v => index++);
然后从字典中找回ID并将其用于排序:
var sortedList = toBeSortedList.OrderBy(x => etalonDictionary[x.Id]).ToList();
答案 1 :(得分:2)
List.IndexOf
将对象作为参数并返回它的索引。您正在传递int
- 值Id
。那不编译。
您可以覆盖Equals
+ GethashCode
并传递x
而不是x.Id
。但在这种情况下我更喜欢List.FindIndex
:
var orderedByIdList = toBeSortedList
.OrderBy(x => etalonList.FindIndex(p => p.Id == x.Id));
以下是覆盖Equals
方法,可以使用IndexOf
:
class Person
{
public int Id { get; set; }
public string Name { get; set; }
public override bool Equals(object obj)
{
if(ReferenceEquals(obj, this))
return true;
Person other = obj as Person;
if (other == null)
return false;
return other.Id == this.Id;
}
public override int GetHashCode()
{
return Id;
}
}
现在这也有效:
var orderedByIdList = toBeSortedList
.OrderBy(x => etalonList.IndexOf(x));
答案 2 :(得分:1)
我猜测etalonList
中的某些值在toBeSortedList
中不存在,因为在所有其他情况下,这个问题毫无意义:
toBeSortedList
的元素未包含在etalonList
中。在这种情况下,问题是不明确的;你会如何订购这些新的名单成员?toBeSortedList
包含与etalonList
完全相同的成员。在这种情况下,只需返回etalonList
或复制它。订购toBeSortedList
的一种天真但简单的方法如下(注意我假设案例1不可能):
static IEnumerable<T> OrderBy(this IEnumerable<T> list, IEnumerable<T> guideList)
{
foreach (var member in guideList)
{
if (toBeSortedList.Contains(member))
yield return member;
}
}
var orderedList = toBeSortedList.OrderBy(etalonList).ToList();
表现不好,但如果列表不是很长,那就应该这样做。
答案 3 :(得分:1)
在这种情况下,你根本不需要定期排序。你可以简单地join带有目标的标准具并投射目标元素。如果标准具不包含所有目标,则可以在排序序列的开头或结尾处连接不存在的项,最终应用一些额外的顺序。
在这两种情况下,您最终都会进行快速O(N)时间复杂度操作。
这是LINQ,它将非现有项放在最后:
var orderedByIdList =
(from a in etalonList join b in toBeSortedList on a.Id equals b.Id select b)
.Concat
(from a in toBeSortedList join b in etalonList on a.Id equals b.Id into b where !b.Any() select a)
.ToList();
答案 4 :(得分:1)
public static IEnumerable<T> OrderBy<T>( this IEnumerable<T> list, IEnumerable<T> guide ) {
var toBeSorted = new HashSet<T>( list );
return guide.Where( member => toBeSorted.Contains( member ) );
}