Нужно найти редкие книги из файла C#

#c# #list

#c# #Список

Вопрос:

нужно найти редкие книги из списка (редкая книга — это книга, которая находится в одном списке, а не в других) вот мой файл списка:

 1;Book1;name1;genre1;publisher1;2015;1000
2;Book2;name2;genre2;publisher2;2015;1000
3;Book3;name3;genre3;publisher3;2015;1000
4;Book4;name4;genre4;publisher4;2015;1000
  

следующий:

 1;Book1;name1;genre1;publisher1;2015;1000
2;Book2;name2;genre2;publisher2;2015;1000
3;Book3;name3;genre3;publisher3;2015;1000
4;Book4;name4;genre4;publisher4;2015;1000
5;Unique;name5;genre5;publisher5;2015;1250
  

в консоли мне нужно получить уникальное название книги, но я получаю:

 1, name1, Book1 , genre1 , publisher1 , 2015 , 1000
2, name2, Book2 , genre2 , publisher2 , 2015 , 1000
3, name3, Book3 , genre3 , publisher3 , 2015 , 1000
4, name4, Book4 , genre4 , publisher4 , 2015 , 1000
5, name5, Unique , genre5 , publisher5 , 2015 , 1250
  

мой код функции:

 public static void RareBook(Padaliniai[] fak)
{
    List<Book> RareBooks = new List<Book>();
    for (int i = 0; i < 2; i  )
    {
        foreach (Book bok in fak[i].GetBookList())
        {
            RareBooks.Add(bok);
        }
    }

    for (int i = 0; i < 2; i  )
    {
        foreach (Book a in fak[0].GetBookList())
        {
            foreach (Book b in fak[1].GetBookList())
            {
                if (a.Pav == b.Pav)
                {
                    RareBooks.Remove(b);
                }
            }
        }
    }

    foreach (Book bok in RareBooks)
    {
        Console.WriteLine("{0}, {1}, {2} , {3} , {4} , {5} , {6}",bok.ISBN,bok.Autorius,bok.Pav,bok.Zanras,bok.Leidykla,bok.Metai,bok.Psl);
    }
}
  

что я делаю не так?

Ответ №1:

Вы добавляете обе записи, поэтому вам нужно удалить обе:

 foreach (Book b in fak[1].GetBookList())
{
  if (a.Pav == b.Pav)
  {
    RareBooks.Remove(a);
    RareBooks.Remove(b);
  }
}
  

Могу ли я просто добавить, что это не идеальное решение? Я бы использовал некоторую логику LINQ для выполнения выбора, отличного от объединения списков… и переопределил Book бы методы равенства, чтобы указать, когда две книги являются одной и той же книгой.

Что-то вроде этого:

 List<Book> rareBooks = fak[0].GetBookList().Except(fak[1].GetBookList())
                      .Union(fak[1].GetBookList().Except(fak[0].GetBookList()))
                      .ToList();
  

Или даже это:

 rarebooks = fak[0].GetBookList().Union(fak[1].GetBookList()).Distinct();
  

В обоих из вышеперечисленных вам необходимо реализовать IEqualityComparer<Book> конечно.

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

1. Список<T>.Метод Remove (T) Удаляет первое вхождение определенного объекта из списка<T>. Можно также использовать removeAll вместо этого.

Ответ №2:

Я бы предпочел LINQ для такого рода операций:

 List<Book> fak0Books = fak[0].GetBookList();
List<Book> fak1Books = fak[1].GetBookList();
List<Book> rareBooks = fak0Books.Where(b0 => fak1Books.All(b1 => b0.Pav != b1.Pav)).
                                 Concat(fak1Books.Where(b1 => fak0Books.All(b0 => b0.Pav != b1.Pav)).
                                 ToList();
  

Для этого берутся все книги, fak[0] для которых нет книг с одинаковым Pav in fak[1] , и все книги, fak[1] для которых нет книг с одинаковым Pav in fak[0] .