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" };

それがオプションでない場合は、Substringまたはをいじる必要があります。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

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

これは、入力内のアイテムの数ではなく、入力内の個別の拡張子の数によって並べ替えがスケーリングされることを意味します。

これにより、2 つの内線番号に同じ優先度を与えることもできます。

于 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.Countくださいm 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 に答える