Func< TElement,TKey1,TKey2>致IComparer< TElement>? [英] Func<TElement, TKey1, TKey2> To IComparer<TElement>?
问题描述
我设法使用这个doohickey [ ^ ]转换Func< TElement,TKey>进入IComparer< telement>。我现在可以创建一个SortedList:
Hi,
I have managed to use this doohickey [^] to convert a Func<TElement, TKey> into a IComparer<telement>. I can now create a SortedList as so:
public OrderedQueue(Func<T, IComparable> orderByFunc, bool @descending = false )
{
Queue = new SortedSet<T>(orderByFunc.ToComparer());
}
....
new OrderedQueue<WorkflowDataAccess.Projections.Message>(m => m.Due);
(是的,我还在使用通用的有序队列)
现在我想要更多。我希望能够传递如下多种功能:
(yes, I am still playing with a generic Ordered Queue)
now I want more. I want to be able to pass in multiple functions as below:
new OrderedQueue<WorkflowDataAccess.Projections.Message>(m=>m.Urgency, m => m.Due);
所以我想我会有第一个func.ToComparer,然后是另一个可以添加该功能的IComparer上的扩展。这就是我被困住的地方。
也许我会以错误的方式去做,或者有更简单的方法来做到这一点,但我有时间去玩^ _ ^
这是我的扩展对象,包括我上面链接的doohickey:
So I figured I would have the first func.ToComparer and then another extension that on that IComparer that could then add the function. This is where I am stuck.
Maybe I'm going about it the wrong way, or there is an easier way to do this, but I have some time to play ^_^
Here are my extension objects including the doohickey I linked above:
public static class FuncExtensions
{
public static IComparer<TElement> ToComparer<TElement, TKey>(this Func<TElement, TKey> func)
{
return new ProjectionComparer<TElement,TKey>(func);
}
public static IComparer<TElement> AddComparison<TElement, TKey>(this IComparer<TElement> comparer,
Func<TElement, TKey> func)
{
//What now?
}
internal class ProjectionComparer<TElement, TKey> : IComparer<TElement>
{
private readonly Func<TElement, TKey> _keySelector;
private readonly IComparer<TKey> _comparer;
internal ProjectionComparer(Func<TElement, TKey> keySelector,
IComparer<TKey> comparer = null)
{
this._keySelector = keySelector;
this._comparer = comparer ?? Comparer<TKey>.Default;
}
public int Compare(TElement x, TElement y)
{
TKey keyX = _keySelector(x);
TKey keyY = _keySelector(y);
return _comparer.Compare(keyX, keyY);
}
}
}
推荐答案
你最容易做的就是板条箱另一个比较器类将连接两个比较器。
The easiest you can do is crate another comparer class that will concatenate the two comparers.
class MultiComparer<TElement> : IComparer<TElement>
{
private readonly IEnumerable<IComparer<<TElement>> comparers;
public MultiComparer(IEnumerable<IComparer<<TElement>> comparers)
{
this.comparers = comparers;
}
public int Compare(TElement x, TElement y)
{
return comparers
.Select(comparer => comparer.Compare(x, y))
.FirstOrDefault(result => result <> 0);
}
}
但也许最好更改ProjectionComparer以支持开箱即用。
我没有通过编译器运行它,但应该足够正确理解。
But maybe it would be better to change ProjectionComparer to support this out of the box.
I didn't run this through the compiler but should be correct enough to understand.
解决方案#1的替代方案可以是可以像这样使用的Comparer:
An alternative to Solution #1 could be a Comparer that can be used like this:
IComparer<DateTime> comparer = ChainedComparer<DateTime>.First(d => d.Year).Then(d => d.Month);
使用以下实现:
With the following implementation:
// Comparer for a prioritized sequence of comparison attributes.
// Implemented as "fluent interface", i.e. usage:
// ChainedComparer<MyType>.First(v=>v.Prop1).Then(v=>v.Prop2)...Then(v=>v.PropN);
public class ChainedComparer<TValue> : IComparer<TValue>
{
// sequence of comparison stages: 1st has 1st priority, next has next priority, etc.
private List<Func<TValue, TValue, int>> _stages;
// private construction. For named constructor see First(...)
private ChainedComparer() { _stages = new List<Func<TValue,TValue,int>>(); }
// named constructor - takes selector for first property for comparison
public static ChainedComparer<TValue> First<TDimension>(Func<TValue, TDimension> selector)
where TDimension : IComparable<TDimension>
{
return new ChainedComparer<TValue>().Then(selector);
}
// selector for next comparison stage
public ChainedComparer<TValue> Then<TDimension>(Func<TValue, TDimension> selector)
where TDimension : IComparable<TDimension>
{
_stages.Add((a, b) => selector(a).CompareTo(selector(b)));
return this;
}
// implementation of IComparer<T> interface
public int Compare(TValue a, TValue b)
{
return _stages.Select(compare => compare(a, b)).FirstOrDefault(res => res != 0);
}
}
干杯
Andi
Cheers
Andi
这就是我的意思在审查了Tomas Takac的解决方案1之后提出了
This is what I came up with after reviewing Solution 1 by Tomas Takac
using System;
using System.Collections.Generic;
using System.Linq;
namespace Extensions.Linq
{
public static class FuncExtensions
{
public static IComparer<TElement> ToComparer<TElement,TKey>(this Func<telement,> func) where TKey : IComparable
{
return new ProjectionComparers<TElement,TKey>(func);
}
public static IComparer<TElement> ToComparer<TElement,TKey>(this IEnumerable<Func<TElement,TKey>> funcs) where TKey : IComparable
{
return new ProjectionComparers<TElement,TKey>(funcs.ToArray());
}
internal class ProjectionComparers<TElement,TKey> : IComparer<TElement> where TKey :IComparable
{
private readonly List<comparedelegate> _compareDelegates = new List<comparedelegate>();
private delegate int CompareDelegate(TElement x, TElement y);
internal ProjectionComparers(params Func<TElement,TKey>[] funcs)
{
foreach (var f in funcs)
{
var func = f;
_compareDelegates.Add(
(x, y) =>
{
TKey keyX = func(x);
TKey keyY = func(y);
return Comparer<TKey>.Default.Compare(keyX, keyY);
});
}
}
//internal ProjectionComparers(params KeyValuePair<Func<TElement,TKey>>,
// IComparer<TKey>>[] comparers)
//{
// foreach (var kvp in comparers)
// {
// var comparer = kvp;
// _compareDelegates.Add(
// (x, y) =>
// {
// TKey keyX = comparer.Key(x);
// TKey keyY = comparer.Key(y);
// return (comparer.Value ?? Comparer<tkey>.Default).Compare(keyX, keyY);
// });
// }
//}
public int Compare(TElement x, TElement y)
{
return _compareDelegates
.Select(compareDelegate => compareDelegate(x, y))
.FirstOrDefault(result => result != 0);
}
}
}
}
尚未测试所以我是我肯定会调整这个解决方案。
编辑:删除了比较器的ctor并坚持认为TKey具有可比性。适合我的情况
Not yet tested so I'm sure I'll be tweaking this solution.
removed the ctor with Comparers and insisted that TKey is comparable. The suits my case fine
这篇关于Func< TElement,TKey1,TKey2>致IComparer< TElement>?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!