C# — Объединение двух списков и перенос дубликатов в новый список, а затем печать этого списка

#c# #list #duplicates

Вопрос:

     {
        public static List<string> DuplicateNames(List<Person> a, List<Person> b)
        {
            List<string> DuplicatePeople = a.Intersect(b).ToList();
        }

        public static void Main(string[] args)
        {
            List<Person> personsA = new List<Person>();
            personsA.Add(new Person("Emma"));
            personsA.Add(new Person("Eva"));
            personsA.Add(new Person("Data"));
            List<Person> personsB = new List<Person>();
            personsB.Add(new Person("Anna"));
            personsB.Add(new Person("Eva"));
            personsB.Add(new Person("Emma"));

            List<string> myDuplicateNames = Program.DuplicateNames(personsA, personsB);

            foreach (String s in myDuplicateNames)
            {
                Console.WriteLine(s);
           }

            Console.Read();
        }
    }
 
     class Person
    {
        private string name;

        public Person(string name)
        {
            Name = name;
        }

        public string Name { get => name; set => name = value; }

    }
 

Как говорится в названии, я пытаюсь объединить список personA и PersonB в новый список с функцией «Дубликаты имен». Затем я хочу вызвать функцию, которая преобразует повторяющиеся имена в новом списке в «myDuplicatenNames» и распечатывает этот список.

Я довольно новичок в C# и не могу заставить его работать. Любая помощь будет признательна!

Ответ №1:

Ваш код может быть изменен для работы с Intersect методом, который вы используете в настоящее время. Проблема в том, что в вашей реализации вы пытаетесь сравнить класс, который вы создали: Person . По умолчанию сравнение выполняется по ссылке, а не по содержимому свойств. Для того, чтобы он работал, вы можете переопределить Equals его в своем Person классе:

 class Person
{
    private string name;

    public Person(string name)
    {
        Name = name;
    }

    public string Name { get => name; set => name = value; }

    public override bool Equals(object obj)
    {
        return obj is Person person amp;amp;
                name == person.name amp;amp;
                Name == person.Name;
    }            
}
 

Еще одно замечание о вашем DuplicateNames методе, его следует изменить, сделайте то, что вы хотите, преобразуйте список Person дубликатов в список дубликатов string с помощью Select метода:

 public static List<string> DuplicateNames(List<Person> a, List<Person> b)
{
    return a.Intersect(b).Select(p => p.Name).ToList();
}
 

Комментарии:

1. Спасибо за ответ, я возьму ответ и изучу его.

Ответ №2:

1-я проблема: a-это список людей, и вы пытаетесь назначить его списку строк. 2-я проблема: 2 человека с одинаковым именем не равны. Вы можете переопределить Equals, но LINQ предлагает вам более гибкий способ.

     public class Person
    {
        public string Name { get; }   // Read-only default property, initialized in constructor.

        public Person(string name)
        {
            Name = name;
        }
    }

    public class Program
    {
        public static List<string> DuplicateNames(List<Person> a, List<Person> b)
        {
            // LINQ 1:
            List<string> duplicatePeople = a
                .Select(a => a.Name)                              // Projecting a list of persons to a list of strings
                .Where(a => b.Select(p => p.Name).Contains(a))   // Check for each item if it's in the list of names of b.
                .ToList();  

            // LINQ 2: Join
            var duplicatePeople2 = a.Join(
                    b,                                    // 2nd List
                    a => a.Name,                          // What ist the key of the first list?
                    b => b.Name,                          // What ist the key of the second list?
                    (a, b) => a)                          // Secting the item of the first list (if you have more properties in class Person, this could be different from the item of the second list)
                .Select(p => p.Name)                      // Again: projecting to a list of strings
                .ToList();
            return duplicatePeople;
        }

        public static void Main(string[] args)
        {
            // List offers an initializer.
            var personsA = new List<Person>()
            {
                new Person("Emma"),
                new Person("Eva"),
                new Person("Data")
            };

            var personsB = new List<Person>()
            {
                new Person("Anna"),
                new Person("Eva"),
                new Person("Emma")
            };

            List<string> myDuplicateNames = DuplicateNames(personsA, personsB);

            foreach (var s in myDuplicateNames)
            {
                Console.WriteLine(s);
            }

            Console.Read();
        }
    }
 

Комментарии:

1. Эти ответы, кажется, работают на меня. Это было намного сложнее, чем я представлял себе в своей голове. Я обязательно изучу и изучу то, что вы предоставили. Спасибо!