Linq の「即時」モードの実装を作成する必要があります (Unity/Mono のメモリ割り当て制限のため - 長い話ですが、それほど重要ではありません)。
私はThenBy
. 私のパフォーマンスが実際の取引よりも 4 倍遅くなるため、これを適用する私の方法には明らかに欠陥があります。
だから私が今していることは -
各OrderBy
,ThenBy
節について
- 各セレクターの結果のリストを作成し、セレクター評価のすべての結果をリストに追加します
- 2 つのパラメーターからインデックス付けされたリストを使用するデフォルトの比較子を使用するラムダを作成します。
次のようになります。
public static IEnumerable<T> OrderByDescending<T,TR>(this IEnumerable<T> source, Func<T,TR> clause, IComparer<TR> comparer = null)
{
comparer = comparer ?? Comparer<TR>.Default;
var linqList = source as LinqList<T>;
if(linqList == null)
{
linqList = Recycler.New<LinqList<T>>();
linqList.AddRange(source);
}
if(linqList.sorter!=null)
throw new Exception("Use ThenBy and ThenByDescending after an OrderBy or OrderByDescending");
var keys = Recycler.New<List<TR>>();
keys.Capacity = keys.Capacity > linqList.Count ? keys.Capacity : linqList.Count;
foreach(var item in source)
{
keys.Add(clause(item));
}
linqList.sorter = (x,y)=>-comparer.Compare(keys[x],keys[y]);
return linqList;
}
public static IEnumerable<T> ThenBy<T,TR>(this IEnumerable<T> source, Func<T,TR> clause, IComparer<TR> comparer = null)
{
comparer = comparer ?? Comparer<TR>.Default;
var linqList = source as LinqList<T>;
if(linqList == null || linqList.sorter==null)
{
throw new Exception("Use OrderBy or OrderByDescending first");
}
var keys = Recycler.New<List<TR>>();
keys.Capacity = keys.Capacity > linqList.Count ? keys.Capacity : linqList.Count;
foreach(var item in source)
{
keys.Add(clause(item));
}
linqList.sorters.Add((z,x,y)=>z != 0 ? z : comparer.Compare(keys[x],keys[y]));
return linqList;
}
次に、並べ替え関数で行うことは、並べ替えを順番に適用するラムダを作成することです。そのため、最終的には a のように見えComparer<int>
、正しい順序を返す関数になります。
それは、この本当に悪いパフォーマンスを開始します。OrderBy
カリー化とおよび関数のさまざまな署名を使用してバージョンを試しましThenBy
たが、実際には何も高速に動作しておらず、マルチキーの並べ替えに関するトリックが欠けているだけなのではないかと思います。
ソート変数と関数:
public List<Func<int,int,int,int>> sorters = new List<Func<int, int, int, int>>();
public Func<int,int,int> sorter;
public List<int> sortList = new List<int>();
bool sorted;
private List<T> myList = new List<T>();
void ResolveSorters()
{
if(sorter==null)
return;
Func<int,int,int> function = null;
if(sorters.Count==0)
{
function = sorter;
}
else
{
function = sorter;
foreach(var s in sorters)
{
var inProgress = function;
var current = s;
function = (x,y)=>current(inProgress(x,y), x,y);
}
}
sortList.Capacity = sortList.Capacity < myList.Count ? myList.Count : sortList.Capacity;
sortList.Clear();
sortList.AddRange(System.Linq.Enumerable.Range(0,myList.Count));
//var c = myList.Count;
/*for(var i =0; i < c; i++)
sortList.Add(i);*/
sortList.Sort(new Comparison<int>(function));
sorted = true;
sorters.Clear();
}