У нас не получилось загрузить Disqus. Если вы модератор, пожалуйста посмотрите наше руководство по устранению неисправностей.

Віталік Бречко • 4 лет назад

Пара слов о перечисленных в статье методах. Для определения эквивалентности они используют методы GetHeshCode() & Equals(). Если вам нужно работать с коллекцией объектов вашего класса, то эти методы, возможно, придется в нём переопределить.



class Program
{
static void Main()
{
List< User> users = new List< User>()
{
new User { Name = "Tom", Age = 33 },
new User { Name = "Tom", Age = 33 },
new User { Name = "Bob", Age = 30 },
new User { Name = "Tom", Age = 21 },
new User { Name = "Sam", Age = 43 },
new User { Name = "Jack", Age = 0 },
new User { Name = "Maks", Age = 21 },
new User { Name = "Nikita", Age = 103 },
new User { Name = "Mike", Age = 3 }
};


foreach (User user in users)
Console.WriteLine($"{user.Name} - {user.Age}");


var distinctedUsers = users.Distinct();
Console.WriteLine("===================");


foreach (User user in distinctedUsers)
Console.WriteLine($"{user.Name} - {user.Age}");


}
}
class User
{
public string Name { get; set; }
public int Age { get; set; }


public override bool Equals(object obj)
{
return obj is User user &&
Name == user.Name &&
Age == user.Age;
}


public override int GetHashCode()
{
return HashCode.Combine(Name, Age);
}
}
HohoMAN • 2 лет назад

Спасибо Виталий, ваши комментарии на сайте самые полезные пожалуй.

Grigoriy • 11 месяцев назад

Касательно последнего примера про выборку сложных объектов.
Метод Equals по умолчанию работает с object типом, из-за чего каждый раз будет происходить боксинг-анбоксинг при проверка каждого из элементов списка, что не самым лучшим образом влияет на производительность.
Нужно реализовать интерфейс IEquatable<t>, чтобы решить эту проблему (это вариант Eqauls с универсальным типом)

Person[] students = { new Person("Tom"), new Person("Bob"), new Person("Sam") };
Person[] employees = { new Person("Tom"), new Person("Bob"), new Person("Mike") };

// объединение последовательностей
var people = students.Union(employees);

foreach (Person person in people)
Console.WriteLine(person.Name);


class Person : IEquatable<person>
{
public string Name { get; }
public Person(string name) => Name = name;

public bool Equals(Person? obj)
{
if (obj is null) return false;
return obj.Name == Name;
}
public override int GetHashCode() => Name.GetHashCode();
}


В этом случае боксинг и анбоксинг происходить не будет. Вот более подробно про это - https://learn.microsoft.com...

Slay • 1 год назад

Кто может, разъясните пожалуйста, зачем в последнем примере нам переопределять в классе методы Equals() GetHashCode(). Когда пробую без них, то списки просто добавляются как при Concat(). Не могу понять механизм. Админ, автор, гуру (не знаю как правильно тебя назвать) расскажи плиззззз.

андрей пупкин • 1 год назад

Для сравнения объектов в последовательностях применяются реализации методов GetHeshCode() и Equals(). Поэтому если мы хотим работать с последовательностями, которые содержат объекты своих классов и структур, то нам необходимо определить для них подобные методы:
еквалс сравнивает ссылки. они всегда разные. поэтому переопределяем

Grigoriy • 11 месяцев назад

все классы - производные от object, у которого и определены методы Equals() и GetHashCode(). Скорее всего при использовании запросов без явного переопределения работает версия методов, определённая в object

YaKotikTvoy • 6 месяцев назад
YaKotikTvoy • 6 месяцев назад

https://uploads.disquscdn.c...
Мелкая опечатка) результирующая

андрей пупкин • 1 год назад

с помощью linq можно сравнивать коллекции внутри коллекции? т.е. сравнивать коллекции, которые являются полем обьекта составляющего другую коллекцию.

Grigoriy • 11 месяцев назад

Да, можно. SelectMany из подтемы "проекция данных" Вам в помощь

Kurulko • 1 год назад

Еще можно сказать, что record классы уже сами по себе генерируют метод Equals, в котором сравнение двух records производится на основе их значений. То есть в классах record мы не сможем переопределять метод Equals:


Person[] students = { new Person("Kurulko", 27), new Person("Kurulko", 18), new Person("Father", 25) };
Person[] employees = { new Person("Chmo", 15), new Person("Kurulko", 18), new Person("Loh", 228) };

foreach (var item in students.Union(employees))
Console.WriteLine(item);

Console.WriteLine(new string('*',10));

foreach (var item in students.Except(employees))
Console.WriteLine(item);

Console.WriteLine(new string('*', 10));

foreach (var item in students.Intersect(employees))
Console.WriteLine(item);


record Person(string Name, int Age)
{
public override int GetHashCode()
=> HashCode.Combine(Name, Age);
public override string ToString()
=> $"Name:{Name} - Age:{Age}";
}

/*
Будет:

Name:Kurulko - Age:27
Name:Kurulko - Age:18
Name:Father - Age:25
Name:Chmo - Age:15
Name:Loh - Age:228
**********
Name:Kurulko - Age:27
Name:Father - Age:25
**********
Name:Kurulko - Age:18
*/
Kurulko • 1 год назад

И без метода GetHashCode, будет работать аналогично

Kurulko • 1 год назад

Было бы неплохо, если бы вставили такие же картинки с объединением, пересечением и разностью коллекций как в swift-e:
https://uploads.disquscdn.c...

Kurulko • 1 год назад

Симметрическая разность в C#:


string[] soft = { "Microsoft", "Google", "Apple" };
string[] hard = { "Apple", "IBM", "Samsung" };

var union = soft.Union(hard);
var intersect = soft.Intersect(hard);
var symmetricDifference = union.Except(intersect);
foreach (string item in symmetricDifference)
Console.WriteLine(item);

/*
Будет:

Microsoft
Google
IBM
Samsung
*/
Alex Veto • 4 лет назад

А почему это называется множеством?
string[] soft = { "Microsoft", "Google", "Apple"};
Сюда ведь можно напихать дубликатов:
string[] soft = { "Microsoft", "Google", "Apple", "Apple", "Apple"};
а во множестве по определению все элементы уникальны

Metanit • 4 лет назад

немного переиначил статью, убрав вообще упоминание о множествах

Metanit • 4 лет назад

да, с одной стороны так, но с другой стороны, microsoft также именует их "Операции над множествами" set operators) например, https://docs.microsoft.com/...

Eugene Samoylenko • 8 лет назад

неплохо было бы рассказать об использовании LINQPad, если у Вас есть опыт его использования.

Gennady Alekseyuk • 6 лет назад

LINQPad зачетная программка, компилит всё без создания солюшена, а рассказывать особо нечего, ставите и будет Вам шасце))
https://uploads.disquscdn.c...

Kades • 2 лет назад

А я просто создал пустой проект в Visual Studio и перезатираю его новыми примерами. Никаких левых прог не нужно.

Met S • 8 лет назад

А можно как-то объединить списки через элемент? Например
{1,2,3} {4,5,6} {7,8,9} ... -> {1,4,7,... 2,5,8,... 3,6,9,...}

Metanit • 8 лет назад

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

Met S • 8 лет назад

То есть вложенные циклы, или как?

Metanit • 8 лет назад

да, можно и через вложенные циклы

Met S • 8 лет назад

а если без циклов можно пример, что-то ничего в голову не приходит?

Тимофей Алейников • 6 лет назад

int[][] a = {
new int[] { 1, 2, 3, 4 },
new int[] { 5, 6 },
new int[] { 7, 8, 9 }
};
var res = a.SelectMany((x, i) => x.Select((y, k) => ((int order, int value))(k * a.Length + i, y)))
.OrderBy(x => x.order).Select(x => x.value);
Console.WriteLine(string.Join(", ", res));

Govard Freeman • 3 лет назад

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

андрей пупкин • 1 год назад

где можно найти подробности по синтаксису, подскажите)

Vlad Viklund • 4 лет назад

Что-то точно будет вложено. Если не циклы, то функции ( как в примере Тимофея )