创建在另一个列表中按顺序排序的排序列表

时间:2020-10-16 01:24:26

标签: c#

我有一个已按优先级排序的项目清单,以及一组未排序的项目。每个未排序的项目可能会也可能不会出现在优先列表中。

如何创建一个新列表,该列表仅包含按优先级列表中出现的顺序显示在优先级列表中的未排序项目?

例如

List<Foo> priorityList = GetPriorityList();
IEnumerable<Foo> unsorteditems = GetSomeItems();

List<Foo> prioritisedItems = new List<Foo>();

foreach (var item in unsorteditems)
{
  if (priorityList.Contains(item))
  {
    //Add item to prioritisedItems in the order it appears in priorityList
  }
}

粗略的实现很容易,但是看起来很杂乱且效率低下:

List<Foo> sortedList = new List<Foo>();

  foreach (var item in unsortedItems)
  {
    if (priorityList.Contains(item) && !sortedList.Contains(item))
    {
      if (sortedList.Count() < 1)
      {
        sortedList.Add(item);
      }
      else
      {
        foreach (var sortedItem in sortedList)
        {
          if (priorityList.IndexOf(sortedItem) < priorityList.IndexOf(item))
          {
            sortedList.Insert(sortedList.IndexOf(sortedItem), item);
            break;
          }
        }
      }
    }
  }

是否有一种更清洁的方法?

有关此主题的其他问题似乎是:a)使用商品的属性进行排序,或b)假定所有未排序的商品都将出现在已排序的列表中。

编辑:

根据要求,以下是此特定情况下的Foo对象:

public partial class Erpstatuscodes
  {
    public string ProgramCode { get; set; }
    public string StatusCode { get; set; }
    public string StatusCodeDescription { get; set; }
    public string ShortDescription { get; set; }
    public string TestInstructions { get; set; }
    public string SampleType { get; set; }
    public string StatusType { get; set; }
  }

unsortedItems将从EntityFramework中拉出,而priorityList项将从配置文件中反序列化。

此外,需要澄清的是,这是使用.NET Framework 4.8,而不是.NET Core。

1 个答案:

答案 0 :(得分:0)

您说Foo没有任何可与之进行比较的成员,因此我假设Fooclass(不是struct),并且您'依赖对象引用相等性(==Object.ReferenceEquals),这就是您的priorityList.IndexOf(sortedItem)代码在幕后所做的工作,下面的代码应在其中起作用:< / p>

Dictionary<Foo,Int32> priorityListIndexes = priorityList
    .Select( ( foo, idx ) => ( foo, idx ) )
    .ToDictionary( t => t.foo, t => t.idx);

List<Foo> prioritisedItems = unsorteditems
    .Select( unsortedFoo => ( foo: unsortedFoo, ok: priorityListIndexes.TryGetValue( unsortedFoo, out Int32 idx ), idx: idx ) )
    .Where( t => t.ok )
    .OrderBy( t => t.idx )
    .Select( t => t.foo )
    .ToList();

请注意,通常来说,将引用类型用于TKey是一个坏主意,但是在这种情况下就可以了。


实际上,这可以简化为单个.Join(同样需要注意的是,连接谓词可以接受Foo引用相等):

List<Foo> prioritisedItems = Enumerable
    .Join<Foo>(
        outer           : priorityList.Select( ( foo, idx ) => ( foo, idx ) ),
        inner           : unsorteditems,
        outerKeySelector: t => t.foo,
        innerKeySelector: foo => foo,
        resultSelector  : ( left, right ) => ( left.idx, right )
    )
    .OrderBy( t => t.idx )
    .Select( t => t.foo )
    .ToList();