1

この SO 記事: LINQ での昇順/降順 - パラメータを使用して順序を変更できますか? 昇順または降順で条件付きで並べ替える方法についての解決策が提示されました。

この記事で取り上げていないのは、クエリ内のデータに基づいて決定を下したい場合 (つまり、実際には何が最も可能性が高いか) ということです。

私はできないようです:

source.OrderByWithDirection(o => o.MyColumnToOrderBy, o => o.SortingDirection)

その後、メソッドを書き直す必要がありますか? どうやって?

- アップデート -

根拠として、これが私が達成しようとしていることです:

Strike  Type Price
98      Ask  101
98      Ask  100
98      Ask  99
98      Bid  95
98      Bid  96
98      Bid  97

ご覧のとおり、アスクは下にソートされますが、入札は上にソートされ、最大の差を持つ行が隣り合っています。だから私が言いたいのは次のようなものです:

source.OrderBy(o => new { o.Strike, o.Type })
  .ThenByWithDirection(o => o.Price, o => o.Type == "Ask" ? __down__ : __up__)

- アップデートⅡ -

これを行う不器用な方法は、次のように 2 つの別個のクエリを発行することです。

source
  .Where(o => o.Type == "Ask")
  .OrderBy(o => new { o.Strike, o.Type })
  .ThenBy(o => o.Price)

source
  .Where(o => o.Type == "Bid")
  .OrderBy(o => new { o.Strike, o.Type })
  .ThenByDescending(o => o.Price)

それらを連結します

4

6 に答える 6

1

そのための一般的な拡張メソッドを作成しました。

public static IEnumerable<T> OrderByString<T>(this IEnumerable<T> entities, string sortExpression)
        {

            bool descending = sortExpression.ToLowerInvariant().Trim().EndsWith("desc");

            PropertyInfo[] propertyInfos = typeof(T).GetProperties();
            // sort properties by name
            foreach (PropertyInfo propertyInfo in propertyInfos)
            {
                if (sortExpression.Split(' ')[0] == propertyInfo.Name)
                {
                    PropertyInfo info = propertyInfo;
                    if (descending)
                        return entities.OrderByDescending(c => info.GetValue(c, null));
                    else
                        return entities.OrderBy(c => info.GetValue(c, null));
                }
            }
            return entities;
        }

使用法:

IEnumerable x = cars.OrderByString("color desc");

それが役に立てば幸い。

ダニエル

于 2013-08-21T05:39:25.550 に答える
1

私はあなたのエンティティ/オブジェクトを持っていませんが、次のようなことはできません:

var items = from t in source
    select new { a = t, b = t.Type == "Ask" ? -t.Price : t.Price };
var sorted = from x in items
     orderby x.a.Type, x.b
     select x.a;

つまり、並べ替えを実行できる単一のプロパティを含む新しいオブジェクトを作成し、それを順序付け操作で使用しますか?

于 2013-08-21T06:18:21.790 に答える
1

1 つの方法は、ソートのために情報をより意味のある構造に抽出することです。

source
    .Select(o => new {
        o.Strike,
        o.Type,
        o.Price,
        o.AskPrice = o.Type == "Ask" ? o.Price : (int)null,
        o.BidPrice = o.Type == "Bid" ? o.Price : (int)null
    })
    .OrderBy(o => o.Strike)
    .ThenBy(o => o.Type)
    .ThenByDescending(o => o.AskPrice)
    .ThenBy(o => o.BidPrice)

これは、これら 2 つの項目で並べ替えたいことがわかっていることを前提としています。

もう 1 つのオプションは、値の 1 つを逆にすることです (たとえば、並べ替えの目的で 1000000 - AskPrice を使用すると、昇順で並べ替えることができます)。

于 2013-08-21T06:30:06.277 に答える
0

カスタムを試すことができますIComparer

public class MyComparer<T> : IComparer<T> {
   public MyComparer(bool ascending){
      Descending = !ascending;
   }
   public bool Descending {get;set;}
   public int Compare(T x, T y){
      //your normal logic
      int result = ....;
      return Descending ? -result : result;
   }
}

次に、OrderByクエリで使用します。

source.OrderBy(o=>o.MyColumnToOrderBy, new MyComparer(true));//true for ascending and false for descending

アップデート

ソート方向を示すenum代わりにsome を使用できます。bool

public class MyComparer<T> : IComparer<T> {
   public MyComparer(SortingDirection sortDir){
      Direction = sortDir;
   }
   public SortingDirection Direction {get;set;}
   public int Compare(T x, T y){
      //your normal logic
      int result = ....;
      return Direction == SortingDirection.Descending ? -result : result;
   }
   public enum SortingDirection {
     Ascending,
     Descending
   }
}
//o.SortingDirection should be type of enum SortingDirection
source.OrderBy(o=>o.MyColumnToOrderBy, new MyComparer(o.SortingDirection));

別の回避策

GroupBy次のように、 order byでちょっとしたトリックを使用できると思いますo.SortingDirection

source.GroupBy(x=>x.MyColumnToOrderBy)
      .SelectMany(g=> o.SortingDirection == SortingDirection.Ascending ? 
                                            g.OrderBy(a=>a.Key) :
                                            g.OrderByDescending(a=>a.Key));
于 2013-08-21T04:26:47.290 に答える
0

一般的に、提案された を実装するのは難しいと思いますOrderByWithDirection。たとえば、データセットの結果はどうなるでしょう{1, true}, {2, false}, {3, true}, {4, false}か? あなたのケースでそれが機能する唯一の理由は、2 番目の並べ替えが最初の並べ替えと高い相関関係にあるためです。つまり、2 番目の並べ替えは「ビッド」と「アスク」を比較する必要はありません。

これにアプローチする最善の方法は、並べ替え全体を実装するカスタム IComparator を使用することです。何かのようなもの:

int Compare(Entry a, Entry b)
{
    if (a.Type == b.Type)
    {
        // same type, look at the price difference and reverse if they are both Bids
        return a.Price.CompareTo(b.Price) * (a.Type == "Bid" ? -1 : 1);
    }
    else
    {
        // different types, Ask comes first
        return (a.Type == "Ask") ? -1 : 1;
    }
}
于 2013-08-21T22:41:49.320 に答える