2 List <T> nasıl birleştirilir ve C # 'da yinelenen değerler kaldırılır


160

Üçüncü listede birleştirmem ve yinelenen değerleri bu listelerden kaldırmam gereken iki listem var

Açıklamak biraz zor, bu yüzden bana kodu neye benzediğini ve sonuç olarak ne istediğini gösteren bir örnek göstereyim, örnekte ResultAnalysisFileSql sınıfı değil int türünü kullanıyorum.

first_list = [1, 12, 12, 5]

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

İki listenin birleştirilmesinin sonucu şu listeyle sonuçlanmalıdır: Sonuç_listesi = [1, 12, 5, 7, 9]

Sonucun, iki "12" değeri de dahil olmak üzere ilk listeye ve ikinci_listede ek bir 12, 1 ve 5 değerine sahip olduğunu fark edeceksiniz.

ResultAnalysisFileSql sınıfı

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


    }

Kopyaları birleştirmek ve kaldırmak için herhangi bir örnek kod var mı?

Yanıtlar:


289

Numaralandırılabilir'e bir göz attınız mı?

Bu yöntem, kopyaları döndürme kümesinden hariç tutar . Bu, çoğaltmalar dahil giriş dizilerindeki tüm öğeleri döndüren Concat yöntemine göre farklı bir davranıştır.

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: Kişiniz Class IEqualityComparer <T> kullanıyor mu? Öyleyse, GetHashCode ve Equals yöntemlerinizi kontrol etmeniz gerekir. Msdn.microsoft.com/en-us/library/bb341731.aspx adresindeki Notlar bölümüne bakın .
Tomas Narros

1
Bunu 2 farklı koleksiyonda kullanarak karşılaştığım için dikkat etmek önemlidir: "Biri diğerinden devralmadığı sürece iki farklı türü birleştiremezsiniz" adresinden stackoverflow.com/a/6884940/410937 bir cannot be inferred from the usagehata verdi .
atconway

30

neden sadece

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

oh ... msdn'ye göre dışarıda bırakabilirsiniz.Distinct()

Bu yöntem, kopyaları dönüş kümesinden hariç tutar


25

Sendika iyi bir performansa sahip değil: Bu makalede , bunları karşılaştırmak

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

Listeler ve LINQ birleştirme: 4820ms
Sözlük birleştirme: 16ms
HashSet ve IEqualityComparer: 20ms
LINQ Birliği ve IEqualityComparer: 24ms


1
Ayrıca bir sözlük birleştirme kullanmanın başka bir yararı -> Ben DB verilerinden geri gelen iki liste var. Verilerimin iki veri listesinden farklı olan bir zaman damgası alanı var. Sendika ile zaman damgasının farklı olması nedeniyle kopyaları alıyorum. Ancak birleştirme ile sözlükte hangi benzersiz alanı dikkate almak istediğime karar verebilirim. +1
JimSan

İşlemci hızına göre değişebilir, sahip olduğunuz CPU türüne bağlıdır.
Asad Ali

7
Makalenin sonunda "LINQ Birliği'ni tercih ediyorum çünkü niyetini çok net bir şekilde iletiyor." ;) (ayrıca, sadece 8 ms fark vardı)
James Wilkins

1
Farkın ihmal edilebilir olduğu küçük listeler için Uniondaha temiz ve daha okunabilir kodlar elde edilir. Kodu yavaş olmadığında hiper optimize etmek için zaman harcamak yolda bir bakım cezasına neden olabilir.
elolos

14

Linq's Union kullanın:

using System.Linq;
var l1 = new List<int>() { 1,2,3,4,5 };
var l2 = new List<int>() { 3,5,6,7,8 };
var l3 = l1.Union(l2).ToList();

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);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.