按外部排序顺序对泛型列表排序



我有一个通用列表

简化示例
var list = new List<string>()
  {
    "lorem1.doc",
    "lorem2.docx",
    "lorem3.ppt",
    "lorem4.pptx",
    "lorem5.doc",
    "lorem6.doc",
  };

我想做的是根据外部列表排序

对这些项进行排序在示例

var sortList = new[] { "pptx", "ppt", "docx", "doc" };
// Or
var sortList = new List<string>() { "pptx", "ppt", "docx", "doc" };

linq有什么内置的东西可以帮助我实现这个目标吗?还是我必须走每一条路?

对于Enumerable.OrderBy,您可以使用IndexOf:

var sorted = list.OrderBy(s => sortList.IndexOf(Path.GetExtension(s)));

因此扩展在sortList中的索引决定了在其他列表中的优先级。未知扩展具有最高优先级,因为它们的索引为-1。

但是你需要在扩展中添加一个点来让它工作:

var sortList = new List<string>() { ".pptx", ".ppt", ".docx", ".doc" };

如果这不是一个选项,你必须摆弄SubstringRemove,例如:

var sorted = list.OrderBy(s => sortList.IndexOf(Path.GetExtension(s).Remove(0,1)));

即使某些文件名没有扩展名,这个解决方案也可以工作:

var sortList = new List<string>() { "pptx", "ppt", "docx", "doc" };
var list = new List<string>()
  {
    "lorem1.doc",
    "lorem2.docx",
    "lorem3.ppt",
    "lorem4.pptx",
    "lorem5.doc",
    "lorem6.doc",
  };
var result = 
       list.OrderBy(f => sortList.IndexOf(Path.GetExtension(f).Replace(".","")));

您可以尝试使用Array.IndexOf()方法:

var sortedList = list.OrderBy(i => sortList.IndexOf(System.IO.Path.GetExtension(i))).ToList();

sortDicionary会更有效率:

var sortDictionary = new Dictionary<string, int> {
    { ".pptx", 0 },
    { ".ppt" , 1 },
    { ".docx", 2 },
    { ".doc" , 3 } };
var sortedList = list.OrderBy(i => {
    var s = Path.GetExtension(i);
    int rank;
    if (sortDictionary.TryGetValue(s, out rank))
        return rank;
    return int.MaxValue; // for unknown at end, or -1 for at start
});

这样查找的是O(1)而不是O(# of extensions)

同样,如果您有大量的文件名和少量的扩展名,使用

可能会更快。
var sortedList = list
    .GroupBy(p => Path.GetExtension(p))
    .OrderBy(g => {
        int rank;
        if (sortDictionary.TryGetValue(g.Key, out rank))
            return rank;
        return int.MaxValue; // for unknown at end, or -1 for at start
    })
    .SelectMany(g => g);

这意味着排序根据输入中不同扩展的数量进行缩放,而不是根据输入中的项数进行缩放。

这也允许你给两个扩展相同的优先级。

这里有另一种不使用OrderBy的方法:

var res = 
sortList.SelectMany(x => list.Where(f => Path.GetExtension(f).EndsWith(x)));

请注意,这种方法的复杂性是O(n * m)n = sortList.Countm list.Count

OrderBy接近最坏情况的复杂性是O(n * m * log m),但可能在一般情况下它会更快(因为IndexOf并不总是导致O(n))。然而,对于小nm,您不会注意到任何差异。

对于大列表,最快的方法(复杂度O(n+m))是构造一个临时查找,即:

var lookup = list.ToLookup(x => Path.GetExtension(x).Remove(0,1));
var res = sortList.Where(x => lookup.Contains(x)).SelectMany(x => lookup[x]);

相关内容

  • 没有找到相关文章

最新更新