วิธีผสาน 2 รายการ <T> และลบค่าที่ซ้ำกันออกจากรายการใน C #


159

ฉันมีสองรายการรายการที่ฉันต้องการรวมในรายการที่สามและลบค่าที่ซ้ำกันออกจากรายการนั้น

ค่อนข้างยากที่จะอธิบายดังนั้นให้ฉันแสดงตัวอย่างของรหัสลักษณะและสิ่งที่ฉันต้องการเป็นผลลัพธ์ในตัวอย่างฉันใช้ int ชนิดไม่ใช่คลาส ResultAnalysisFileSql

first_list = [1, 12, 12, 5]

second_list = [12, 5, 7, 9, 1]

ผลลัพธ์ของการรวมสองรายการควรเป็นผลลัพธ์ในรายการนี้: result_list = [1, 12, 5, 7, 9]

คุณจะสังเกตเห็นว่าผลลัพธ์มีรายการแรกรวมถึงค่า "12" สองรายการและใน second_list มีค่าเพิ่มเติม 12, 1 และ 5

คลาส ResultAnalysisFileSql

[Serializable]
    public partial class ResultAnalysisFileSql
    {
        public string FileSql { get; set; }

        public string PathFileSql { get; set; }

        public List<ErrorAnalysisSql> Errors { get; set; }

        public List<WarningAnalysisSql> Warnings{ get; set; }

        public ResultAnalysisFileSql()
        {

        }

        public ResultAnalysisFileSql(string fileSql)
        {
            if (string.IsNullOrEmpty(fileSql)
                || fileSql.Trim().Length == 0)
            {
                throw new ArgumentNullException("fileSql", "fileSql is null");
            }

            if (!fileSql.EndsWith(Utility.ExtensionFicherosErrorYWarning))
            {
                throw new ArgumentOutOfRangeException("fileSql", "Ruta de fichero Sql no tiene extensión " + Utility.ExtensionFicherosErrorYWarning);
            }

            PathFileSql = fileSql;
            FileSql = ObtenerNombreFicheroSql(fileSql);
            Errors = new List<ErrorAnalysisSql>();
            Warnings= new List<WarningAnalysisSql>();
        }

        private string ObtenerNombreFicheroSql(string fileSql)
        {
            var f = Path.GetFileName(fileSql);
            return f.Substring(0, f.IndexOf(Utility.ExtensionFicherosErrorYWarning));
        }


        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;
            if (!(obj is ResultAnalysisFileSql))
                return false;

            var t = obj as ResultAnalysisFileSql;
            return t.FileSql== this.FileSql
                && t.PathFileSql == this.PathFileSql
                && t.Errors.Count == this.Errors.Count
                && t.Warnings.Count == this.Warnings.Count;
        }


    }

มีโค้ดตัวอย่างใดบ้างสำหรับการรวมและลบรายการที่ซ้ำกันออก

คำตอบ:


288

คุณได้ดูEnumerable แล้วยูเนี่ยน

วิธีนี้ไม่รวมรายการที่ซ้ำกันจากชุดผลตอบแทน นี่คือพฤติกรรมที่แตกต่างไปจากวิธี Concat ซึ่งจะคืนค่าองค์ประกอบทั้งหมดในลำดับการป้อนข้อมูลรวมถึงรายการที่ซ้ำกัน

List<int> list1 = new List<int> { 1, 12, 12, 5};
List<int> list2 = new List<int> { 12, 5, 7, 9, 1 };
List<int> ulist = list1.Union(list2).ToList();

// ulist output : 1, 12, 5, 7, 9

6
@Dr TJ: Class บุคคลของคุณใช้ IEqualityComparer <T> หรือไม่ ถ้าเป็นเช่นนั้นคุณจะต้องตรวจสอบวิธี GetHashCode และ Equals ของคุณ ดูส่วนหมายเหตุของmsdn.microsoft.com/en-us/library/bb341731.aspx
Tomas Narros

1
สิ่งสำคัญที่ควรทราบเนื่องจากฉันพบปัญหาในการใช้สิ่งนี้ในคอลเล็กชันที่ต่างกัน 2 รายการ: "คุณไม่สามารถรวมสองประเภทที่แตกต่างกันได้เว้นแต่ว่าจะได้รับมรดกจากอีกประเภทหนึ่ง" จากstackoverflow.com/a/6884940/410937ซึ่งให้cannot be inferred from the usageข้อผิดพลาด
atconway

30

ทำไมไม่ง่าย ๆ เช่น

var newList = list1.Union(list2)/*.Distinct()*//*.ToList()*/;

โอ้ ... ตามmsdnคุณสามารถละทิ้ง.Distinct()

วิธีการนี้จะแยกรายการที่ซ้ำกันออกจากชุดการส่งคืน


25

Union มีประสิทธิภาพไม่ดี: บทความนี้อธิบายเกี่ยวกับการเปรียบเทียบด้วยกัน

var dict = list2.ToDictionary(p => p.Number);
foreach (var person in list1)
{
        dict[person.Number] = person;
}
var merged = dict.Values.ToList();

รายการและการผสาน LINQ: 4820 มิลลิวินาทีการ
ผสานพจนานุกรม: 16ms
HashSet และ IEqualityComparer: 20ms
LINQ Union และ IEqualityComparer: 24ms


1
ข้อดีอีกอย่างของการใช้การผสานพจนานุกรม -> ฉันมีสองรายการที่กลับมาจากฐานข้อมูล และข้อมูลของฉันมีฟิลด์การประทับเวลาซึ่งแตกต่างกันในสองรายการข้อมูล ด้วยการรวมฉันได้รับซ้ำเนื่องจากการประทับเวลาจะแตกต่างกัน แต่ด้วยการผสานฉันสามารถตัดสินใจว่าจะใช้ฟิลด์ใดที่ไม่เหมือนใครในพจนานุกรม +1
JimSan

สามารถแตกต่างกันตามความเร็วโปรเซสเซอร์ขึ้นอยู่กับชนิดของ CPU ที่คุณมี
ซาดอาลี

7
และในตอนท้ายของบทความมันบอกว่า "ฉันชอบ LINQ Union เพราะมันเป็นการสื่อความตั้งใจอย่างชัดเจน" ;) (มีความแตกต่างเพียง 8 ms เท่านั้น)
James Wilkins

1
สำหรับรายการขนาดเล็กที่มีความแตกต่างเล็กน้อยจะทำให้Unionโค้ดสะอาดและอ่านง่ายขึ้น การใช้เวลากับโค้ดไฮเปอร์ - ออปติไมซ์เมื่อไม่ช้าอาจต้องเสียค่าบำรุงรักษาตามถนน
elolos


11
    List<int> first_list = new List<int>() {
        1,
        12,
        12,
        5
    };

    List<int> second_list = new List<int>() {
        12,
        5,
        7,
        9,
        1
    };

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