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

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

  List<MyObject> myList

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

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

 myList.Add(nextObject);

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

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

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

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

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

84
задан EstevaoLuis 13 June 2019 в 13:57
поделиться

6 ответов

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

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

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

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

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

132
ответ дан 24 November 2019 в 08:26
поделиться

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

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

4
ответ дан 24 November 2019 в 08:26
поделиться

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

bool alreadyExists = myList.Any(x=> x.Foo=="ooo" && x.Bar == "bat");
48
ответ дан 24 November 2019 в 08:26
поделиться

Редактировать: Сначала я сказал:


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


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

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

3
ответ дан 24 November 2019 в 08:26
поделиться

Вы уверены, что в данном случае вам нужен список? Если вы заполняете список большим количеством элементов, производительность пострадает при использовании 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 в самом классе.

7
ответ дан 24 November 2019 в 08:26
поделиться

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

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]);
                }
            }
        }
    }
}

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

3
ответ дан 24 November 2019 в 08:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: