Як об'єднати список 2 <T> та видалити з нього повторювані значення у C #


159

У мене є два списки списку, які мені потрібно об'єднати в третьому списку та видалити з цього списку повторювані значення

Трохи важко пояснити, тому дозвольте мені показати приклад того, як виглядає код і що я хочу в результаті, у зразку я використовую тип int, а не клас ResultAnalysisFileSql.

first_list = [1, 12, 12, 5]

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

Результат об'єднання двох списків має призвести до цього списку: результуючий список = [1, 12, 5, 7, 9]

Ви помітите, що результат має перший список, включаючи два його значення "12", а у другому_лісті додаткове значення 12, 1 і 5.

РезультатАналізFileSql клас

[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

Ви подивилися на Unumerable.Union

Цей метод виключає дублікати з набору повернення . Це інша поведінка методу 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: Чи реалізує ваша особа Клас IEqualityComparer <T>? Якщо це так, вам потрібно перевірити методи GetHashCode та Equals. Див. Розділ "Зауваження" на сторінці msdn.microsoft.com/en-us/library/bb341731.aspx .
Томаш Наррос

1
Важливо зазначити, що я зіткнувся з проблемами, використовуючи це у двох різних колекціях: "Ви не можете об'єднати два різних типи, якщо один не успадковує інший" від stackoverflow.com/a/6884940/410937, який спричинив cannot be inferred from the usageпомилку.
atconway

30

чому не просто напр

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

о ... згідно з msdn ви можете залишити його.Distinct()

Цей метод виключає дублікати з набору повернення


25

Союз не має хороших показників: у цій статті описано порівняння їх із собою

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

Списки та злиття LINQ: 4820ms Злиття
словника:
16ms HashSet та IEqualityComparer: 20ms
LINQ Union та IEqualityComparer: 24ms


1
Також ще одна перевага використання словника злиття -> У мене є два списки, що повертаються з даних БД. І мої дані мають поле часової позначки, яке відрізняється у двох списках даних. За допомогою союзу я отримую дублікати через те, що часова марка відрізняється. Але за допомогою злиття я можу вирішити, яке унікальне поле я хочу розглянути у словнику. +1
JimSan

Може залежати від швидкості процесора, залежно від типу процесора.
Асад Алі

7
І в кінці статті сказано: "Я віддаю перевагу LINQ Union, тому що він повідомляє про наміри дуже чітко". ;) (також було лише 8 мс різниця)
Джеймс Вілкінс

1
Для невеликих списків, де різниця незначна, Unionпризводить до отримання більш чіткого та читального коду. Витрата часу на гіпероптимізацію коду, коли це не повільно, може призвести до покарання за технічне обслуговування вниз.
елолос


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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.