5

私の問題は、常に特定の方法でオブジェクトのコレクションを注文したいということです。

例えば:

class foo{
public string name {get;set;}
public DateTime date {get;set;}
public int counter {get;set;}
}

..。

IEnumerable<foo> dosomething(foo[] bar){ 
return bar.OrderBy(a=>a.name).ThenBy(a=>a.date).ThenBy(a=>a.counter);
}

私が抱えている問題は、常にソート順での非常に長い時間のかかる取り組みです。きちんとした解決策は、を実装するクラスを作成するだけのように見えますIComparer<foo>。つまり、次のことができます。

IEnumerable<foo> dosomething(foo[] bar){ 
return bar.OrderBy(a=>a, new fooIComparer())
}

問題は、これが実装する注文方法は次のとおりです。

..。

public int Compare(foo x, foo y){ }

つまり、非常にきめ細かく比較します。

現在の実装(疑似コードを書いていますが、おそらく機能します)

public int Compare(foo x, foo y){
if (x==y)
  return 0;
var order = new []{x,y}.OrderBy(a=>a.name).ThenBy(a=>a.date).ThenBy(a=>a.counter);
  return (order[0] == x) ? -1 : -1;//if x is first in array it is less than y, else it is greater
}

これは正確には効率的ではありませんが、別の方法でより適切なソリューションを提供できますか?理想的には、Compare(x、y)メソッドをまったく使用しませんか?

4

4 に答える 4

3

オプション1-比較者

複数の条件で注文しているため、それぞれのケースで個別に確認します。たとえば、x.namey.nameが等しい場合は、とをチェックx.datey.dateます。

public class FooComparer : IComparer<Foo>
{
    public int Compare(Foo x, Foo y)
    {
       // nasty null checks!
        if (x == null || y == null)
        {
            return x == y ? 0
                : x == null ? -1
                : 1;
        }

        // if the names are different, compare by name
        if (!string.Equals(x.Name, y.Name))
        {
            return string.Compare(x.Name, y.Name);
        }

        // if the dates are different, compare by date
        if (!DateTime.Equals(x.Date, y.Date))
        {
            return DateTime.Compare(x.Date, y.Date);
        }

        // finally compare by the counter
        return x.Counter.CompareTo(y.Counter);
    }
}

オプション2-拡張メソッド

それほど魅力的ではない代替のアプローチは、拡張方法である可能性があります。残念ながら、TKeyそれぞれのforは異なる可能性があるため、ジェネリックスの能力は失われますが、この場合ThenByは安全にタイプに置き換えることができます。object

public static IOrderedEnumerable<T> OrderByThen<T>(this IEnumerable<T> source, Func<T, object> selector, params Func<T, object>[] thenBySelectors)
{
    IOrderedEnumerable<T> ordered = source.OrderBy(selector);
    foreach (Func<T, object> thenBy in thenBySelectors)
    {
        ordered = ordered.ThenBy(thenBy);
    }

    return ordered;
}
于 2013-02-20T10:01:45.757 に答える
2

すべてのプロパティを実装IComparable<foo>して比較する必要があります。

class foo: IComparable<foo>, IComparer<foo>
{
    public string name { get; set; }
    public DateTime date { get; set; }
    public int counter { get; set; }

    public int Compare(foo x, foo y)
    {
        if (x == null || y == null) return int.MinValue;
        if (x.name != y.name)
            return StringComparer.CurrentCulture.Compare(x.name, y.name);
        else if (x.date != y.date)
            return x.date.CompareTo(y.date);
        else if (x.counter != y.counter)
            return x.counter.CompareTo(y.counter);
        else
            return 0;
    }

    public int CompareTo(foo other)
    {
        return Compare(this, other);
    }
}

次に、次のように使用できますOrderBy

var ordered = foos.OrderBy(f => f).ToList();
于 2013-02-20T10:14:35.173 に答える
1

拡張メソッドの何が問題になっていますか?

于 2013-02-20T09:57:12.423 に答える
1

なぜあなたは単にあなたの価値観を比較しないのですか?

int Compare(foo x, foo y)
{

    if (x== null && y == null)
        return 0;
    else if (x == null)
        return -1;
    else if (y == null)
        return 1;

    var nameComparision = string.Compare(x.name,y.name);
    if (nameComparision != 0)
        return nameComparision;
    var dateComparision = x.date.CompareTo(y.date);
    if (dateComparision != 0)
        return dateComparision;
    var counterComparision  = x.counter.CompareTo(y.counter);
    return counterComparision;
}
于 2013-02-20T10:02:06.460 に答える