6

我有一个通用列表

简化示例

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 有什么内置的东西可以帮助我实现这一目标,还是我必须采用 foreach 方式?

4

5 回答 5

8

使用列表,您可以IndexOf使用Enumerable.OrderBy

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

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

但是您需要在扩展中添加一个点才能使其正常工作:

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

如果这不是一个选项,您必须摆弄Substringor Remove,例如:

var sorted = list.OrderBy(s => sortList.IndexOf(Path.GetExtension(s).Remove(0,1)));
于 2013-01-09T11:45:01.823 回答
6

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

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(".","")));
于 2013-01-09T11:45:05.647 回答
1

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

var sortedList = list.OrderBy(i => sortList.IndexOf(System.IO.Path.GetExtension(i))).ToList();
于 2013-01-09T11:45:22.400 回答
1

AsortDicionary会更有效:

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);

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

这也允许您为两个扩展赋予相同的优先级。

于 2013-01-09T11:56:09.930 回答
0

这是另一种不使用的方式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]);
于 2013-01-09T11:57:03.113 回答