Как получить разницу в двух списках на С#?

Итак, у меня есть два списка в С#

List<Attribute> attributes = new List<Attribute>();
List<string> songs = new List<string>();

один из строк, и один из объектов-атрибутов, которые я создал.. очень просто

class Attribute
{
    public string size { get; set; }
    public string link { get; set; }
    public string name { get; set; }
    public Attribute(){}
    public Attribute(string s, string l, string n) 
    {
        size = s;
        link = l;
        name = n;
    }
}

Теперь мне нужно сравнить, какие песни нет в имени атрибутов, например,

songs.Add("something"); 
songs.Add("another"); 
songs.Add("yet another");

Attribute a = new Attribute("500", "http://google.com", "something" ); 
attributes.Add(a);

Мне нужен способ вернуть "другое" и "еще одно", потому что они не находятся в имени списка атрибутов

поэтому для псевдокода

difference = songs - attributes.names

Ответ 1

var difference = songs.Except(attributes.Select(s=>s.name)).ToList();

изменить

Добавлен ToList(), чтобы сделать его списком

Ответ 2

Стоит отметить, что ответы, размещенные здесь, вернут список songs, отсутствующий в attributes.names, но он не даст вам список attributes.names, отсутствующий в songs.

В то время как это то, что хотел OP, заголовок может немного вводить в заблуждение, особенно если (например, я) вы пришли сюда, чтобы узнать, отличается ли содержимое двух списков. Если это то, что вы хотите, вы можете использовать следующее: -

var differences = new HashSet(songs);
differences.SymmetricExceptWith(attributes.Select(a => a.name));
if (differences.Any())
{
    // The lists differ.
}

Ответ 3

var diff = songs.Except(attributes.Select(a => a.name)).ToList();

Ответ 4

Это способ найти все песни, которые не включены в имена атрибутов:

var result = songs
  .Where(!attributes.Select(a => a.name).ToList().Contains(song));

Ответ с использованием Except также является идеальным и, вероятно, более эффективным.

EDIT: этот синтакс имеет одно преимущество, если вы используете его в LINQ to SQL: он преобразуется в предикат SQL NOT IN. Except не переводится ни на что в SQL. Таким образом, в этом контексте все записи будут восстановлены из базы данных и исключены на стороне приложения, что намного менее эффективно.