【问题标题】:Sort in-memory list by another in-memory list按另一个内存列表排序内存列表
【发布时间】:2014-07-12 14:42:50
【问题描述】:

是否可以通过另一个列表对内存中的列表进行排序(第二个列表将是参考数据源或类似的东西)?

public class DataItem
{
    public string Name { get; set; }
    public string Path { get; set; }
}

// a list of Data Items, randomly sorted
List<DataItem> dataItems = GetDataItems();

// the sort order data source with the paths in the correct order
IEnumerable<string> sortOrder = new List<string> {
    "A",
    "A.A1",
    "A.A2",
    "A.B1"
};

// is there a way to tell linq to sort the in-memory list of objects
// by the sortOrder "data source"
dataItems = dataItems.OrderBy(p => p.Path == sortOrder).ToList();

【问题讨论】:

    标签: c# asp.net linq linq-to-sql


    【解决方案1】:

    首先,让我们为sortOrder 中的每个项目分配一个索引:

    var sortOrderWithIndices = sortOrder.Select((x, i) => new { path = x, index = i });
    

    接下来,我们加入两个列表并排序:

    var dataItemsOrdered =
     from d in dataItems
     join x in sortOrderWithIndices on d.Path equals x.path //pull index by path
     orderby x.index //order by index
     select d;
    

    这也是您在 SQL 中的做法。

    【讨论】:

      【解决方案2】:

      这是另一种(我认为更有效)的方法,可以替代被接受为答案的方法。

      List<DataItem> dataItems = GetDataItems();
      IDictionary<string, int> sortOrder = new Dictionary<string, int>()
      {
           {"A", int.MaxValue},
           {"A.A1", int.MaxValue-1},
           {"A.A2", int.MaxValue -2},
           {"A.B1", int.MaxValue-3},
      };
      
      dataItems.Sort((di1, di2) => sortOrder[di1.Path].CompareTo(sortOrder[di2.Path]));
      

      假设Sort()OrderBy() 都采用O(n*logn),其中ndataItems 中的项目数。这里给出的解决方案需要 O(n*logn) 来执行排序。我们假设创建字典 sortOrder 所需的步骤与在原始帖子中创建 IEnumerable 的成本没有显着差异。

      执行join然后 对集合进行排序,但是会增加额外的成本 O(nm),其中 m 是 sortOrder 中的元素数。因此,该解决方案的总时间复杂度为 O(nm + nlogn)。

      理论上,使用join 的方法可以归结为 O(n * (m + logn)) ~= O(n*logn) 任何方式。但实际上,join 会花费额外的周期。这是在 linq 方法中可能产生的额外空间复杂性的补充,其中可能已创建辅助集合以处理 linq 查询。

      【讨论】:

        【解决方案3】:

        如果您的路径列表很大,最好根据字典执行查找:

        var sortValues = sortOrder.Select((p, i) => new { Path = p, Value = i })
                                  .ToDictionary(x => x.Path, x => x.Value);
        
        dataItems = dataItems.OrderBy(di => sortValues[di.Path]).ToList();
        

        【讨论】:

        • 完美运行。实际上,路径列表包含大约 1,400 个项目
        【解决方案4】:

        自定义排序是通过使用作为第二个参数传递给 OrderBy 方法的自定义比较器(IComparer 接口的实现)来完成的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-10-31
          • 2021-03-10
          • 2021-08-06
          • 1970-01-01
          • 2022-07-05
          • 2011-04-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多