Подтвердить что ты не робот

Как проверить, существует ли объект в списке

У меня есть список

  List<MyObject> myList

и я добавляю элементы в список, и я хочу проверить, есть ли этот объект уже в списке.

Итак, прежде чем я сделаю это:

 myList.Add(nextObject);

Я хочу посмотреть, есть ли следующий объект в списке.

Объект "MyObject" имеет ряд свойств, но сравнение основано на сопоставлении двух свойств.

Каков наилучший способ сделать проверку, прежде чем я добавлю новый "MyObject" в этот список "MyObject".

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

Любые другие более чистые решения, использующие список или LINQ или что-то еще?

4b9b3361

Ответ 1

Это зависит от потребностей конкретной ситуации. Например, словарьный подход был бы неплохим, предполагая:

  • Список относительно стабилен (не много вложений/исключений, для которых словари не оптимизированы)
  • Список достаточно велик (в противном случае служебные данные словаря бессмысленны).

Если вышеизложенное не соответствует вашей ситуации, просто используйте Any():

Item wonderIfItsPresent = ...
bool containsItem = myList.Any(item => item.UniqueProperty == wonderIfItsPresent.UniqueProperty);'

Это будет перечисляться по списку, пока не найдет совпадение, или пока оно не достигнет конца.

Ответ 2

Просто используйте метод Contains. Обратите внимание, что он работает на основе функции равенства Equals

bool alreadyExist = list.Contains(item);

Ответ 3

Если он поддерживает эти два свойства, вы можете:

bool alreadyExists = myList.Any(x=> x.Foo=="ooo" && x.Bar == "bat");

Ответ 4

Вы уверены, что вам нужен список в этом случае? Если вы заполняете список множеством элементов, производительность будет страдать с помощью myList.Contains или myList.Any; время выполнения будет квадратичным. Возможно, вы захотите рассмотреть возможность использования лучшей структуры данных. Например,

 public class MyClass
    {
        public string Property1 { get; set; }
        public string Property2 { get; set; }

    }

    public class MyClassComparer : EqualityComparer<MyClass>
    {
        public override bool Equals(MyClass x, MyClass y)
        {
            if(x == null || y == null)
               return x == y;

            return x.Property1 == y.Property1 && x.Property2 == y.Property2;
        }

        public override int GetHashCode(MyClass obj)
        {
            return obj == null ? 0 : (obj.Property1.GetHashCode() ^ obj.Property2.GetHashCode());
        }
    }

Вы можете использовать HashSet следующим образом:

  var set = new HashSet<MyClass>(new MyClassComparer());
  foreach(var myClass in ...)
     set.Add(myClass);

Конечно, если это определение равенства для MyClass является "универсальным", вам не нужно писать реализацию IEqualityComparer; вы можете просто переопределить GetHashCode и Equals в самом классе.

Ответ 5

Еще один момент, который следует упомянуть, заключается в том, что вы должны обеспечить, чтобы ваша функция равенства была такой, какой вы ожидаете. Вы должны переопределить метод equals, чтобы настроить, какие свойства вашего объекта должны совпадать, чтобы два экземпляра считались равными.

Тогда вы можете просто сделать mylist.contains(пункт)

Ответ 6

Изменить: я сначала сказал:


Что нелепо говорит о решении словаря. Мне кажется, это очень элегантно, потому что вам нужно установить компаратора при создании словаря.


Конечно, но нецелесообразно использовать что-то в качестве ключа, когда это также значение.

Поэтому я бы использовал HashSet. Если последующие операции потребовали индексации, я бы создал список из него, когда было добавлено добавление, иначе просто используйте hashset.

Ответ 7

Вот быстрое консольное приложение, чтобы отобразить концепцию решения вашей проблемы.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    public class myobj
    {
        private string a = string.Empty;
        private string b = string.Empty;

        public myobj(string a, string b)
        {
            this.a = a;
            this.b = b;
        }

        public string A
        {
            get
            {
                return a;
            }
        }

        public string B
        {
            get
            {
                return b;
            }
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            List<myobj> list = new List<myobj>();
            myobj[] objects = { new myobj("a", "b"), new myobj("c", "d"), new myobj("a", "b") };


            for (int i = 0; i < objects.Length; i++)
            {
                if (!list.Exists((delegate(myobj x) { return (string.Equals(x.A, objects[i].A) && string.Equals(x.B, objects[i].B)) ? true : false; })))
                {
                    list.Add(objects[i]);
                }
            }
        }
    }
}

Наслаждайтесь!

Ответ 8

Простой, но он работает

MyList.Remove(nextObject)
MyList.Add(nextObject)

или

 if (!MyList.Contains(nextObject))
    MyList.Add(nextObject);