จัดเรียงรายการคลาสที่กำหนดเอง <T>


112

ฉันต้องการจัดเรียงรายการของฉันกับdateทรัพย์สิน

นี่คือคลาสที่กำหนดเองของฉัน:

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; }
    }
}

นี่คือสิ่งListที่ฉันต้องการจัดเรียง:

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

สิ่งที่ฉันต้องการทำคือจัดเรียงรายการตามdateคุณสมบัติของคลาส cTag วันที่อยู่ในรูปแบบ: dd.MM.yyyy

ฉันอ่านบางอย่างเกี่ยวกับIComparableอินเทอร์เฟซ แต่ไม่รู้วิธีใช้

คำตอบ:


143

วิธีหนึ่งที่ทำได้คือใช้ไฟล์ 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); });

98
คุณสามารถเขียนสิ่งเดียวกันด้วยนิพจน์แลมบ์ดา:list.Sort((a,b) => a.date.CompareTo(b.date));
Xavier Poinas

2
@Xavier ด้วยเหตุผลบางประการจิตใจของฉันยังคงกระโดดไปที่เพรดิเคตก่อนเสมอแม้ว่าคุณจะถูกต้อง 100% ที่นิพจน์แลมด้าของคุณจะทำงานได้สำเร็จและอาจอ่าน / เข้าใจได้ง่ายกว่า
ahsteele

วิธีนี้หรือคุณจะทำลายเน็คไทอย่างสม่ำเสมอโดยใช้นิพจน์แลมบ์ดาได้อย่างไร จะเกิดอะไรขึ้นถ้า a.date == b.date ที่นี่? list.Sort ((a, b) => a.date.CompareTo (b.date)); สิ่งนี้จะสร้างปัญหาเมื่อเพจกริดและทั้งสองเกิดตกในเพจต่างกันหรือไม่
TheEmirOfGroofunkistan

1
@TheEmirOfGroofunkistan ว่าทั้งหมดขึ้นอยู่กับวิธีCompareToการใช้งาน IComparableผู้รับว่าคลาสจะมีวิธีการอย่างไร แต่การเปรียบเทียบนั้นขึ้นอยู่กับผู้สร้างคลาสอย่างไร ไม่แน่ใจว่า Date ใช้ ICompare อย่างไร แต่บ่อยครั้งที่ฉันเห็นนักพัฒนาใช้พารามิเตอร์คำสั่งถูกส่งผ่านเพื่อทำลายการผูกเมื่อค่าเท่ากัน HTH
ahsteele

51

คุณถูกต้องที่คลาส cTag ของคุณต้องใช้IComparable<T>อินเทอร์เฟซ จากนั้นคุณก็สามารถโทรเข้ามาSort()ในรายการของคุณได้

ในการใช้งานIComparable<T>อินเทอร์เฟซคุณต้องใช้CompareTo(T other)วิธีการ วิธีที่ง่ายที่สุดคือเรียกเมธอด CompareTo ของฟิลด์ที่คุณต้องการเปรียบเทียบซึ่งในกรณีของคุณคือวันที่

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);
    }
}

อย่างไรก็ตามสิ่งนี้จะเรียงลำดับได้ไม่ดีเพราะจะใช้การเรียงลำดับแบบคลาสสิกในสตริง (เนื่องจากคุณประกาศวันที่เป็นสตริง) ดังนั้นฉันคิดว่าสิ่งที่ดีที่สุดที่ควรทำคือกำหนดคลาสใหม่และประกาศวันที่ไม่ใช่สตริง แต่เป็น DateTime รหัสจะยังคงเหมือนเดิม:

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);
    }
}

สิ่งเดียวที่คุณต้องทำเมื่อสร้างอินสแตนซ์ของคลาสเพื่อแปลงสตริงของคุณที่มีวันที่เป็นประเภท DateTime แต่สามารถทำได้อย่างง่ายดายเช่นโดยDateTime.Parse(String)วิธีการ


38

สำหรับกรณีนี้คุณสามารถจัดเรียงโดยใช้ LINQ:

week = week.OrderBy(w => DateTime.Parse(w.date)).ToList();


9

สิ่งแรกอันดับแรกหากคุณสมบัติวันที่จัดเก็บวันที่ให้จัดเก็บโดยใช้ DateTime หากคุณแยกวิเคราะห์วันที่ผ่านการจัดเรียงที่คุณต้องแยกวิเคราะห์สำหรับแต่ละรายการที่เปรียบเทียบนั่นก็ไม่ได้มีประสิทธิภาพมากนัก ...

จากนั้นคุณสามารถสร้าง 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());

คุณสามารถทำได้ในฐานะผู้รับมอบสิทธิ์:

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;
          });

6

คุณพูดถูก - คุณต้องใช้ IComparable ในการดำเนินการนี้เพียงแค่ประกาศชั้นเรียนของคุณ:

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

ใน CompareTo คุณเพียงแค่ใช้อัลกอริทึมการเปรียบเทียบที่กำหนดเองของคุณ (คุณสามารถใช้ออบเจ็กต์ DateTime เพื่อทำสิ่งนี้ได้ แต่อย่าลืมตรวจสอบประเภทของ "obj" ก่อน) สำหรับข้อมูลเพิ่มเติมโปรดดูที่นี่และที่นี่


7
IComparable<T>น่าจะเป็นทางเลือกที่ดีกว่าเนื่องจากมีการตรวจสอบตามความชอบเป็นIComparable: msdn.microsoft.com/en-us/library/b0zbh7b6.aspx
Richard Szalay


3

ดูวิธีการเรียงลำดับที่มากเกินไปของคลาส List มีบางวิธีที่จะทำได้ หนึ่งในนั้น: คลาสที่กำหนดเองของคุณต้องใช้อินเตอร์เฟส IComparable จากนั้นคุณก็ใช้วิธีการเรียงลำดับของคลาส List


3

ขอบคุณสำหรับคำตอบที่รวดเร็วทั้งหมด

นี่คือทางออกของฉัน:

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

ขอบคุณ


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.