Sortir Daftar Kelas Kustom <T>

112

Saya ingin mengurutkan daftar saya dengan dateproperti.

Ini adalah kelas khusus saya:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Test.Web
{
    public class cTag
    {
        public int id { get; set; }
        public int regnumber { get; set; }
        public string date { get; set; }
    }
}

Dan ini Listyang saya ingin urutkan:

List<cTag> Week = new List<cTag>();

Yang ingin saya lakukan adalah mengurutkan Daftar menurut dateproperti kelas cTag. Tanggal ist dalam format: dd.MM.yyyy.

Saya membaca sesuatu tentang IComparableantarmuka, tetapi tidak tahu cara menggunakannya.

Manusia serigala
sumber

Jawaban:

143

Salah satu cara untuk melakukannya adalah dengan a delegate

List<cTag> week = new List<cTag>();
// add some stuff to the list
// now sort
week.Sort(delegate(cTag c1, cTag c2) { return c1.date.CompareTo(c2.date); });
ahsteele
sumber
98
Anda juga dapat menulis hal yang sama dengan ekspresi lambda:list.Sort((a,b) => a.date.CompareTo(b.date));
Xavier Poinas
2
@Xavier karena alasan tertentu, pikiran saya masih selalu melompat ke predikat terlebih dahulu, meskipun Anda 100% benar bahwa ekspresi Lambda Anda akan menyelesaikan pekerjaan dan mungkin lebih mudah dibaca / dipahami.
ahsteele
bagaimana ini, atau bagaimana Anda, memutuskan hubungan secara konsisten menggunakan ekspresi lambda? Bagaimana jika a.date == b.date disini? list.Sort ((a, b) => a.date.CompareTo (b.date)); Apakah ini akan menimbulkan masalah saat paging grid dan keduanya jatuh pada halaman yang berbeda?
TheEmirOfGroofunkistan
1
@TheEmirOfGroofunkistan yang semuanya tergantung pada bagaimana CompareTodiimplementasikan. IComparablepenerima hibah bahwa suatu kelas akan memiliki metode tersebut, tetapi bagaimana cara membandingkannya, terserah pembuat kelas. Tidak yakin bagaimana Tanggal mengimplementasikan ICompare, tetapi sering kali saya telah melihat pengembang menggunakan parameter urutan diteruskan untuk memutuskan hubungan ketika nilainya sama. hth
ahsteele
51

Anda benar bahwa kelas cTag Anda harus mengimplementasikan IComparable<T>antarmuka. Kemudian Anda bisa memanggil Sort()di daftar Anda.

Untuk mengimplementasikan IComparable<T>antarmuka, Anda harus mengimplementasikan CompareTo(T other)metode. Cara termudah untuk melakukannya adalah dengan memanggil metode CompareTo dari bidang yang ingin Anda bandingkan, yang dalam kasus Anda adalah tanggal.

public class cTag:IComparable<cTag> {
    public int id { get; set; }
    public int regnumber { get; set; }
    public string date { get; set; }
    public int CompareTo(cTag other) {
        return date.CompareTo(other.date);
    }
}

Namun, ini tidak akan diurutkan dengan baik, karena ini akan menggunakan pengurutan klasik pada string (karena Anda menyatakan tanggal sebagai string). Jadi menurut saya hal terbaik untuk dilakukan adalah dengan mendefinisikan ulang kelas dan menyatakan tanggal bukan sebagai string, tetapi sebagai DateTime. Kode tersebut akan tetap hampir sama:

public class cTag:IComparable<cTag> {
    public int id { get; set; }
    public int regnumber { get; set; }
    public DateTime date { get; set; }
    public int CompareTo(cTag other) {
        return date.CompareTo(other.date);
    }
}

Hanya hal yang harus Anda lakukan saat membuat instance kelas untuk mengubah string Anda yang berisi tanggal menjadi tipe DateTime, tetapi hal itu dapat dilakukan dengan mudah misalnya dengan DateTime.Parse(String)metode.

Ondra C.
sumber
38

Untuk kasus ini, Anda juga dapat mengurutkan menggunakan LINQ:

week = week.OrderBy(w => DateTime.Parse(w.date)).ToList();
Yakimych
sumber
12
List<cTag> week = new List<cTag>();
week.Sort((x, y) => 
    DateTime.ParseExact(x.date, "dd.MM.yyyy", CultureInfo.InvariantCulture).CompareTo(
    DateTime.ParseExact(y.date, "dd.MM.yyyy", CultureInfo.InvariantCulture))
);
Darin Dimitrov
sumber
9

Hal pertama yang pertama, jika properti tanggal menyimpan tanggal, simpanlah menggunakan DateTime. Jika Anda mengurai tanggal melalui urutan yang harus Anda parse untuk setiap item yang dibandingkan, itu tidak terlalu efisien ...

Anda kemudian dapat membuat IComparer:

public class TagComparer : IComparer<cTag>
{
    public int Compare(cTag first, cTag second)
    {
        if (first != null && second != null)
        {
            // We can compare both properties.
            return first.date.CompareTo(second.date);
        }

        if (first == null && second == null)
        {
            // We can't compare any properties, so they are essentially equal.
            return 0;
        }

        if (first != null)
        {
            // Only the first instance is not null, so prefer that.
            return -1;
        }

        // Only the second instance is not null, so prefer that.
        return 1;
    }
}

var list = new List<cTag>();
// populate list.

list.Sort(new TagComparer());

Anda bahkan dapat melakukannya sebagai delegasi:

list.Sort((first, second) =>
          {
              if (first != null && second != null)
                  return first.date.CompareTo(second.date);

              if (first == null && second == null)
                  return 0;

              if (first != null)
                  return -1;

              return 1;
          });
Matthew Abbott
sumber
6

Anda benar - Anda perlu menerapkan IComparable. Untuk melakukan ini, cukup nyatakan kelas Anda:

public MyClass : IComparable
{
  int IComparable.CompareTo(object obj)
  {
  }
}

Di CompareTo, Anda cukup menerapkan algoritme perbandingan kustom Anda (Anda dapat menggunakan objek DateTime untuk melakukan ini, tetapi pastikan untuk memeriksa jenis "obj" terlebih dahulu). Untuk informasi lebih lanjut, lihat di sini dan di sini .

AJ.
sumber
7
IComparable<T>mungkin akan menjadi pilihan yang lebih baik, karena dicentang dalam preferensi untuk IComparable: msdn.microsoft.com/en-us/library/b0zbh7b6.aspx
Richard Szalay
5

Anda bisa menggunakan linq:

var q = from tag in Week orderby Convert.ToDateTime(tag.date) select tag;
List<cTag> Sorted = q.ToList()
SirDemon
sumber
3

lihat metode Sortir kelas List yang kelebihan beban. ada beberapa cara untuk itu. salah satunya: kelas kustom Anda harus mengimplementasikan antarmuka IComparable kemudian Anda dapat menggunakan metode Sortir kelas Daftar.

Arseny
sumber
3

Terima kasih untuk semua Jawaban cepat.

Ini solusi saya:

Week.Sort(delegate(cTag c1, cTag c2) { return DateTime.Parse(c1.date).CompareTo(DateTime.Parse(c2.date)); });

Terima kasih

Manusia serigala
sumber
2
YourVariable.Sort((a, b) => a.amount.CompareTo(b.amount));
sansalk
sumber