web-dev-qa-db-ja.com

LINQ-複数のリスト<T>を組み合わせて値で並べ替える(.Net 3.5)

いくつかの_List<T> where T:IGetTime_を組み合わせようとしています(つまり、Tには常にメソッドgetTime()があります)。

次に、getTime()が返すDateTimeでアイテムを並べ替えようとしています。

私のLINQは次のようになります。

_public static List<T> Combine(List<T> one, List<T> two, List<T> three)
    {
        var result = from IGetTime item in one
                     from IGetTime item2 in two
                     from IGetTime item3 in three
                     select new{ item, item2, item3 };

        return result.ToList();
    }
_

まだorderbyを追加していません。これは次のようになります。

_var thestream = from T item in this
                orderby item.getTime() descending
                select item;
_

とにかく、最終的なリストを組み合わせて注文することはできますか????

前もって感謝します、

ロベルト

21
Roberto Bonini

ここには3つのリストがあります-何正確に注文しようとしていますか?

キャストも正しくありません。結果はIEnumerable<X>になります。ここで、Xは3つのTが含まれる匿名型です。

アイデアが本当にconcatenate 3つのリストを並べ替える場合は、次のようにします。

return one.Concat(two)
          .Concat(three)
          .OrderByDescending(x => x.GetTime())
          .ToList();
26
Jon Skeet

これが私がそれをする方法です:

public static List<T> Combine<T, TKey>
(
  Func<T, TKey> orderingFunction,
  params IEnumerable<T>[] theParams
)
  where TKey : IComparable
{
  return theParams
    .SelectMany(x => x)
    .OrderBy(orderingFunction)
    .ToList();
}

ここにいくつかのテストコードがあります:

    public static void Test1()
    {
        List<int> a = new List<int>() { 1, 2, 3 };
        List<int> b = new List<int>() { 3, 2, 1 };
        List<int> c = CombineLists.Combine(i => i, a, b);
        c.ForEach(i => Console.WriteLine(i));
    }

ストーリーは次のとおりです。

public static List<T> Combine<T, TKey>
(
  Func<T, TKey> orderingFunction,
  params IEnumerable<T>[] theParams
)
  where TKey : IComparable

このシグニチャは、2つの型パラメータ、いくつかの順序付け関数と一連のコレクションを受け取るメソッドを宣言します。タイプTおよびTKeyは、テスト呼び出しで明示的に指定されていないことに注意してください。コンパイラには、これらのタイプが何であるかを理解するための小さなパズルがあります。最初に、与えられたIEnumerables(aおよびb)を検査し、それらがintのIEnumerableであることを検出します。ああ、Tはintでなければなりません。次に、順序付け関数を調べて、渡されたのと同じ型が返されることを確認します。ああ、TKeyはintでなければなりません。

whereはちょっと面白いです。 OrderByは、(コンパイル時に)TKeyがIComparableであることを確認する必要があります。実行時にのみチェックするため、コードでコンパイル時のチェックを行うことができます。

params 必要な数のパラメーターを受け取り、それらが配列を作成することを参照します。誰が3つのリストに制限したいですか?

        return theParams
            .SelectMany(x => x)
            .OrderBy(orderingFunction)
            .ToList();

SelectMany コレクションのコレクションを解凍します。これは、階層の1つのレベルをフラット化する方法です。 OrderBy は、各要素を注文可能な値に投影する関数を取り、それらの値に従って要素を並べ替えます。 ToList クエリを列挙し、リストを返します。そこに驚きはありません。

4
Amy B