Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Distinct в Liste 
V
    Опции темы
Stratus
Дата 9.8.2011, 23:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 27.5.2009

Репутация: нет
Всего: нет



Коллеги не могу разобраться как использовать по назначению Distinct, когда изначально есть List объективов и 
distinct нужно применить к определенному полю объекта?

Вот этот код не работает...
Код

    class Program
    {
        static List<Objects> Obj = new List<Objects>(); 
        static string[] DistinctStrings;

        static void Main(string[] args)
        {
            Obj.Add(new Objects("TextF1","Text_F21"));
            Obj.Add(new Objects("TextF1_1","Text_F21_1"));
            Obj.Add(new Objects("TextF1_1","Text_F21_1"));

            DistinctStrings = Obj.Distinct().ToString().ToArray();

            foreach (string DS in DistinctStrings)
                Console.WriteLine(DS);

            Console.ReadLine( );
        }
    }

    class Objects
    {
        string Field1;
        string Field2;

        public Objects(string Field1, string Field2)
        {
            this.Field1 = Field1;
            this.Field2 = Field2;
        }

        public string F1 {get {return Field1; }}
        public string F2 {get {return Field2; }}
    }

PM MAIL   Вверх
WarHog
Дата 10.8.2011, 09:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 122
Регистрация: 20.10.2007
Где: Воронеж

Репутация: нет
Всего: 2



Во-первых, в твоем случае Distinct'у нужно передать класс, реализующий IEqualityComparer<Objects>, в котором ты задаешь, по каким критериям будет работать дистинкт. Например, в простейшем случае, если тебе нужно применение к F1, то нужно что-то вроде такого:
Код

class Comparer : IEqualityComparer<Objects>
    {
        public bool Equals(Objects x, Objects y)
        {
            return x.F1 == y.F1;
        }

        public int GetHashCode(Objects obj)
        {
            return obj.F1.GetHashCode();
        }
    }

Но в таком случае для каждого нового типа сравнения придется определять новый класс компарера. Лучше сделать его универсальным, как-то так:
Код

class UniversalComparer<T> : IEqualityComparer<T>
    {
        private readonly Func<T, T, bool> _compareFunc;
        private readonly Func<T, int> _hashFunc;

        public UniversalComparer(Func<T, T, bool> compareFunc, Func<T, int> hashFunc)
        {
            _compareFunc = compareFunc;
            _hashFunc = hashFunc;
        }

        public bool Equals(T x, T y)
        {
            return _compareFunc(x, y);
        }

        public int GetHashCode(T obj)
        {
            return _hashFunc(obj);
        }
    }

здесь в конструкторе ты передаешь делегаты, которые определяют сравнение твоих объектов между собой и взятие хэша для объекта. Работать это все будет так:
Код

            var res = Obj.Distinct(
                new UniversalComparer<Objects>((o1, o2) => o1.F1 == o2.F1, o => o.F1.GetHashCode()));

Соответственно, в делегатах вместо F1 можно взять любое свойство.

Во-вторых, такое
Код

.Distinct().ToString().ToArray()

приведет к тому, что у тебя будет массив из Char'ов, который ты потом запихиваешь в foreach и Char пытаешься неявно прокастить в строке.
Делай что-то вроде
Код

var res = Obj.Distinct(...);
            foreach (var DS in res)
                Console.WriteLine(DS.F1);

ну или переопределяй ToString у Objects'а  smile
--------------------
PM MAIL   Вверх
Stratus
Дата 10.8.2011, 18:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 27.5.2009

Репутация: нет
Всего: нет



Отлично. Спасибо за развернутый ответ!
Я честно говоря пробовал создать Comparer реализовав этот интерфейс прям в классе обьекта Objects, но потом не смог его оттуда вытащить.
Получается из-за одного поля создавать отдельный класс...
А насколько этот способ быстрый если например сравнить его с обычным перебором т.е. выделить поле из объекта прошедшись по нему перебором, а затем взять Distinct()?
PM MAIL   Вверх
WarHog
Дата 10.8.2011, 21:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 122
Регистрация: 20.10.2007
Где: Воронеж

Репутация: нет
Всего: 2



Цитата

Получается из-за одного поля создавать отдельный класс...

Ну если ты сделаешь дженерик компаратор, то сможешь его использовать для любого типа.
Цитата

А насколько этот способ быстрый если например сравнить его с обычным перебором т.е. выделить поле из объекта прошедшись по нему перебором, а затем взять Distinct()?

т.е. сделать что-то вроде
Код

Obj.Select(o => o.F1).Distinct();

? так будет, во-первых, только медленнее, а, во-вторых, на выходе ты получаешь IEnumerable<string>, в отличие от IEnumerable<T>
Медленнее, потому что будет лишний select и потому что Distinct, не получив компарера, будет использовать в данном случае дефолтный  GenericEqualityComparer<string> и дергать внутри тот же самый x.Equals(y).
--------------------
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0807 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.