Сравнить общую коллекцию? - PullRequest
1 голос
/ 25 марта 2011

у меня есть

ObservableCollection<BasicClass> allCollection;
ObservableCollection<BasicClass> selectedCollection;

, где

BasicClass
{
public Name {get;set;}
public Age {get;set;}
}

Теперь я добавил много BasicClass предметов к allCollection и выбрал только BasicClass к selectedCollection

SomeWhere, куда я хочу добавить элементы в selectedCollection, которых нет в allCollection. Я попробовал это

 foreach(var a in allCollection)
    {
          foreach(var s in selectedCollection)
             if(a.Name!=s.Name)
              //selectedCollection.Add(new BasicClass {Name =a.Name, Age=a.Age}); 
    }

Но проблема в том, что этот код добавляет новый BasicClass для каждого непревзойденного имени, но мое требование - для каждого Name of allCollection сравнить все элементы selectedCollection. Если его там нет, добавьте еще ход для следующего элемента.

Решение LINQ может помочь этому? На самом деле, я добился этого с помощью флагов if и if, но это выглядит очень беспокойно. Мое традиционное решение

    foreach(var a in allCollection)
       {
           bool same = false;
           foreach(var s in selectedCollection)
             if(a.Name==s.Name)
               same=true;
        }
   if(same==false)
     selectedCollection.Add(new BasicClass {Name =a.Name, Age=a.Age}); 

И я ненавижу это ..

EDIT:

Я не хочу сравнивать коллекцию с коллекцией. Я хочу сравнить значение collection1 с collection2 всех значений, и если его там нет, то я хочу добавить

Ответы [ 4 ]

1 голос
/ 25 марта 2011

Вы уверены, что вам это не нужно?

        foreach(var a in allCollection)    
        {    
            if (!selectedCollection.Contains(a))
                selectedCollection.Add(new BasicClass {Name =a.Name, Age=a.Age});     
        }

EDIT

Я только что видел ваш комментарий ниже о совпадении только по имени, поэтому вышеприведенное не совсем то, что вы хотите :). Попробуйте этот подход вместо:

        foreach(var a in allCollection)
        {
            if (!selectedCollection.Any(s => a.Name == s.Name))
            {
                selectedCollection.Add(new BasicClass {Name =a.Name, Age=a.Age});     
            }
        }

EDIT

Как предположил Крис, вы также можете использовать «Кроме» для создания коллекции. Я не уверен, что это принесет много пользы, возможно, это будет быстрее, но это потребует написания кода для сравнения и создания новой временной коллекции. Тем не менее, это довольно кратко, например После того, как вы написали компаратор, вам просто понадобится добавить недостающие элементы в коллекцию:

selectedCollection.Concat(allCollection.Except(selectedCollection));
1 голос
/ 25 марта 2011

Итак, в основном вам нужно «где-не-в»? Linq-> Except - это путь для фильтрации на BasicClass.name реализует только IEqualityComparer для Except.

1 голос
/ 25 марта 2011

Я не уверен, что правильно понял ваши требования, поэтому я могу упустить смысл ...

Ваш BasicClass должен реализовать интерфейс IEquatable<BasicClass>, так что два экземпляра BasicClassможно сравнить на равенство:

class BasicClass : IEquatable<BasicClass>
{
    public Name {get;set;}
    public Age {get;set;}

    public bool Equals(BasicClass other)
    {
        if (other == null)
            return false;
        return string.Equals(this.Name, other.Name);
    }

    public override int GetHashCode()
    {
        return Name == null ? 0 : Name.GetHashCode();
    }
}

Теперь вы можете использовать метод Except, чтобы найти элементы, которые находятся в allCollection, но не в selectedCollection:

BasicClass[] notSelected = allCollection.Except(selectedCollection).ToArray();
foreach(BasicClass item in notSelected)
{
    selectedCollection.Add(item);
}

Альтернативновы можете реализовать IEqualityComparer<BasicClass> и передать его Except (вместо реализации IEquatable<BasicClass> в BasicClass)

0 голосов
/ 25 марта 2011

Вы правы, это легче сделать с помощью Linq:

var itemsToAdd = allCollection.Except(selectedCollection);
foreach (var item in itemsToAdd)
    selectedCollection.Add(item);

С другой стороны, это просто приведет к тому, что оба списка будут содержать одинаковые элементы.Конечно, это то, что вы хотите?

Если BasicItem переопределяет 'Equals' и 'GetHashCode' на основе Name, то это все, что вам нужно.Если этого не произойдет, вам также потребуется реализовать IEqualityComparer :

//Allows us to compare BasicItems as if Name is the key
class NameComparer: IEqualityComparer<BasicItem>
{
    public bool Equals(BasicItem first, BasicItem second)
    {
        return first.Name == second.Name;
    }

    public int GetHashCode(BasicItem value)
    {
        return value.Name.GetHashCode;
    }
}

Теперь вы передаете экземпляр этого класса в Except:

var itemsToAdd = allCollections.Except(selectedCollection, new NameComparer());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...