18

IComparable昇順または降順で並べ替え、並べ替えているオブジェクト タイプのさまざまなフィールドで並べ替えることができるように、インターフェイスを使用する方法の基本的な例が必要です。

4

6 に答える 6

14

使用しているので、たとえば、をList<T>使用する方がはるかに簡単です。Comparison<T>

List<Foo> data = ...
// sort by name descending
data.Sort((x,y) => -x.Name.CompareTo(y.Name));

もちろん、LINQを使用すると、次のものを使用できます。

var ordered = data.OrderByDescending(x=>x.Name);

List<T>ただし、これを(インプレースの再注文のために)非常に簡単に再導入できます。ラムダ構文Sortでonを許可する例を次に示します。List<T>

using System;
using System.Collections.Generic;  

class Foo { // formatted for vertical space
    public string Bar{get;set;}
}
static class Program {
    static void Main() {
        List<Foo> data = new List<Foo> {
            new Foo {Bar = "abc"}, new Foo {Bar = "jkl"},
            new Foo {Bar = "def"}, new Foo {Bar = "ghi"}
        };
        data.SortDescending(x => x.Bar);
        foreach (var row in data) {
            Console.WriteLine(row.Bar);
        }
    }

    static void Sort<TSource, TValue>(this List<TSource> source,
            Func<TSource, TValue> selector) {
        var comparer = Comparer<TValue>.Default;
        source.Sort((x,y)=>comparer.Compare(selector(x),selector(y)));
    }
    static void SortDescending<TSource, TValue>(this List<TSource> source,
            Func<TSource, TValue> selector) {
        var comparer = Comparer<TValue>.Default;
        source.Sort((x,y)=>comparer.Compare(selector(y),selector(x)));
    }
}
于 2009-01-12T13:47:57.763 に答える
12

簡単な例を次に示します。

public class SortableItem : IComparable<SortableItem>
{
    public int someNumber;

    #region IComparable<SortableItem> Members

    public int CompareTo(SortableItem other)
    {
        int ret = -1;
        if (someNumber < other.someNumber)
            ret = -1;
        else if (someNumber > other.someNumber)
            ret = 1;
        else if (someNumber == other.someNumber)
            ret = 0;
        return ret;
    }

    #endregion
}

「それは素晴らしいことですが、並べ替え順序を制御したり、別のフィールドで並べ替えたりするにはどうすればよいでしょうか?」

単純。あとは、オブジェクトにいくつかのフィールドを追加するだけです。まず、別の並べ替えタイプの文字列を追加します。次に、降順または昇順のどちらで並べ替えるかを示すブール値を追加します。次に、検索するフィールドを決定するフィールドを追加します。

public class SortableItem : IComparable<SortableItem>
{
    public enum SortFieldType { SortNumber, SortString }

    public int someNumber = -1;
    public string someString = "";
    public bool descending = true;    
    public SortFieldType sortField = SortableItem.SortFieldType.SortNumber;        

    #region IComparable<SortableItem> Members

    public int CompareTo(SortableItem other)
    {
        int ret = -1;
        if(sortField == SortableItem.SortFieldType.SortString)
        {
            // A lot of other objects implement IComparable as well.
            // Take advantage of this.
            ret = someString.CompareTo(other.someString);
        }
        else
        {
            if (someNumber < other.someNumber)
                ret = -1;
            else if (someNumber > other.someNumber)
                ret = 1;
            else if (someNumber == other.someNumber)
                ret = 0;
        }
        // A quick way to switch sort order:
        // -1 becomes 1, 1 becomes -1, 0 stays the same.
        if(!descending) ret = ret * -1; 

        return ret;
    }

    #endregion

    public override string ToString()
    {
       if(sortField == SortableItem.SortFieldType.SortString)
          return someString;
       else
          return someNumber.ToString();
    }
}

"どうするか教えて!"

あなたがとてもうまく尋ねたからです。

static class Program
{
    static void Main()
    {

        List<SortableItem> items = new List<SortableItem>();
        SortableItem temp = new SortableItem();
        temp.someString = "Hello";
        temp.someNumber = 1;
        items.Add(temp);
        temp = new SortableItem();
        temp.someString = "World";
        temp.someNumber = 2;
        items.Add(temp);
        SortByString(items);
        Output(items);
        SortAscending(items);
        Output(items);
        SortByNumber(items);
        Output(items);
        SortDescending(items);
        Output(items);
        Console.ReadKey();
    }

    public static void SortDescending(List<SortableItem> items)
    {
        foreach (SortableItem item in items)
            item.descending = true;
    }
    public static void SortAscending(List<SortableItem> items)
    {
        foreach (SortableItem item in items)
            item.descending = false;
    }
    public static void SortByNumber(List<SortableItem> items)
    {
        foreach (SortableItem item in items)
            item.sortField = SortableItem.SortFieldType.SortNumber;
    }
    public static void SortByString(List<SortableItem> items)
    {
        foreach (SortableItem item in items)
            item.sortField = SortableItem.SortFieldType.SortString;
    }
    public static void Output(List<SortableItem> items)
    {
        items.Sort();
        for (int i = 0; i < items.Count; i++)
            Console.WriteLine("Item " + i + ": " + items[i].ToString());
    }
}
于 2009-01-12T13:34:12.033 に答える
4

動的ソートが必要な場合は、LINQを使用できます

var itemsOrderedByNumber = ( from item in GetClasses() orderby item.Number select item ).ToList();
var itemsOrderedByText = ( from item in GetClasses() orderby item.Text select item ).ToList();
var itemsOrderedByDate = ( from item in GetClasses() orderby item.Date select item ).ToList();

またはListクラスの「Sort」メソッド:

List<Class1> itemsOrderedByNumber2 = new List<Class1>( GetClasses() );
itemsOrderedByNumber2.Sort( ( a, b ) => Comparer<int>.Default.Compare( a.Number, b.Number ) );

List<Class1> itemsOrderedByText2 = new List<Class1>( GetClasses() );
itemsOrderedByText2.Sort( ( a, b ) => Comparer<string>.Default.Compare( a.Text, b.Text ) );

List<Class1> itemsOrderedByDate2 = new List<Class1>( GetClasses() );
itemsOrderedByDate2.Sort( ( a, b ) => Comparer<DateTime>.Default.Compare( a.Date, b.Date ) );
于 2009-01-12T13:47:39.307 に答える
0
using System;
using System.Collections.Generic;
using System.Text;

namespace Sorting_ComplexTypes
{
    class Program
    {
        static void Main(string[] args)
        {
            Customer customer1 = new Customer {
                ID = 101,
                Name = "Mark",
                Salary = 2400,
                Type = "Retail Customers"
            };
            Customer customer2 = new Customer
            {
                ID = 102,
                Name = "Brian",
                Salary = 5000,
                Type = "Retail Customers"
            };
            Customer customer3 = new Customer
            {
                ID = 103,
                Name = "Steve",
                Salary = 3400,
                Type = "Retail Customers"
            };

            List<Customer> customer = new List<Customer>();
            customer.Add(customer1);
            customer.Add(customer2);
            customer.Add(customer3);

            Console.WriteLine("Before Sorting");
            foreach(Customer c in customer)
            {
                Console.WriteLine(c.Name);
            }

            customer.Sort();
            Console.WriteLine("After Sorting");
            foreach(Customer c in customer)
            {
                Console.WriteLine(c.Name);
            }

            customer.Reverse();
            Console.WriteLine("Reverse Sorting");
            foreach (Customer c in customer)
            {
                Console.WriteLine(c.Name);
            }
            }
        }
    }
    public class Customer : IComparable<Customer>
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Type { get; set; }

        public int CompareTo(Customer other)
        {
            return this.Name.CompareTo(other.Name);
        }
    }
于 2015-06-20T18:11:14.470 に答える
0

これはソート順とは関係ないかもしれませんが、それでも - 私が思うに - の興味深い使い方ですIComparable:

public static void MustBeInRange<T>(this T x, T minimum, T maximum, string paramName)
where T : IComparable<T>
{
    bool underMinimum = (x.CompareTo(minimum) < 0);
    bool overMaximum = (x.CompareTo(maximum) > 0);
    if (underMinimum || overMaximum)
    {
        string message = string.Format(
            System.Globalization.CultureInfo.InvariantCulture,
            "Value outside of [{0},{1}] not allowed/expected",
            minimum, maximum
        );
        if (string.IsNullOrEmpty(paramName))
        {
            Exception noInner = null;
            throw new ArgumentOutOfRangeException(message, noInner);
        }
        else
        {
            throw new ArgumentOutOfRangeException(paramName, x, message);
        }
    }
}

public static void MustBeInRange<T>(this T x, T minimum, T maximum)
where T : IComparable<T> { x.MustBeInRange(minimum, maximum, null); }

これらの単純な拡張メソッドを使用すると、次のIComparableように実装する任意の型のパラメーター範囲チェックを実行できます。

public void SomeMethod(int percentage, string file) {
    percentage.MustBeInRange(0, 100, "percentage");
    file.MustBeInRange("file000", "file999", "file");
    // do something with percentage and file
    // (caller will have gotten ArgumentOutOfRangeExceptions when applicable)
}
于 2009-01-12T14:25:48.187 に答える