Группировать и удалять повторяющиеся данные в списках c # - PullRequest
1 голос
/ 29 марта 2019

Я хотел бы знать, как добиться группировки и удаления повторяющихся данных, например, у меня есть этот класс:

public class MyObject
{
    public string attrb1{ get; set; }
    public string attrb2{ get; set; }
}

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

List<MyObject> ListObject = new List<MyObject>();

var obj1 = new MyObject{attrb1="attrb1", attrb2="attrb2"}
ListObject.Add(obj1);

var obj2 = new MyObject{attrb1="attrb1", attrb2="attrb2"}
ListObject.Add(obj2);


List<MyObject> GroupedList= new List<MyObject>();

foreach(var obj in ListObject)
{
    if(!GroupedList.Contains(obj))
        GroupedList.Add(obj);
}

Ответы [ 4 ]

1 голос
/ 29 марта 2019

То, что вы ищете, это .Distinct(). Чтобы использовать его для пользовательских объектов, сначала необходимо определить EqualityComparer , вот так:

public class MyObjectComparer : EqualityComparer<MyObject>
{
    public override bool Equals(MyObject x, MyObject y)
    {
        return x.attrb1 == y.attrb1 && x.attrb2 == y.attrb2;
    }

    public override int GetHashCode(MyObject obj)
    {
        return (obj.attrb1 + obj.attrb2).GetHashCode();
    }
}

Тогда вы можете использовать его как (таким образом полностью исключая цикл for):

var distinct = ListObject.Distinct(new MyObjectComparer());
1 голос
/ 29 марта 2019

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

Если вы хотите определить другой способ определения равенства, вам необходимо переопределить метод EqualsGetHashCode).

Похоже, что вы хотите считать два экземпляра MyObject равными, если оба их свойства attrib1 равны, а их свойства attrib2 равны. Если это так, вы можете переопределить Equals следующим образом:

public class MyObject
{
    public string attrb1 { get; set; }
    public string attrb2 { get; set; }

    public override bool Equals(object obj)
    {
        var other = obj as MyObject;
        return other != null && other.attrb1 == attrb1 && other.attrb2 == attrb2;
    }

    public override int GetHashCode()
    {
        return (attrb1 + attrb2).GetHashCode();
    }
}

После этого изменения GroupedList в вашем примере кода будет содержать только один элемент.

0 голосов
/ 29 марта 2019

Лучшим решением будет использовать Enumerable.Union, который вернет новый список с union обоих наборов.Для этого нам потребуется переопределить Object.Equals, чтобы быть уверенным, что будут сравниваться только свойства, а не ссылки

. Чтобы упростить задачу, мы будем использовать * 1012.*

/// <summary>
/// Inherit from interface <see cref="IEquatable{T}"/>
/// </summary>
public class Objeto : IEquatable<Objeto>
{
    public string atributo1 { get; set; }
    public string atributo2 { get; set; }

    /// <summary>
    /// Implements <see cref="Equals(Objeto)"/> method from interface <see cref="IEquatable{T}"/>
    /// </summary>
    /// <param name="other">The second object we will compare.</param>
    /// <returns></returns>
    public bool Equals(Objeto other)
    {
        //If the object is null, are not equal.
        if(other==null)return false;
        //If isn't null we compare both attributes.
        return atributo1==other.atributo1&&atributo2==other.atributo2;
    }

    //Override Equals calling the Equals(Object) implementation.
    public override bool Equals(object obj) => Equals(obj as Objeto);

    //override GetHashCode making sure that if Equals is true, both objects must have the same HashCode.
    public override int GetHashCode()
    {
        return atributo1.GetHashCode() ^ atributo2.GetHashCode();
    }
}

Теперь мы можем использовать Enumerable.Union с объектами типа Objeto

List<Objeto> list1 = new List<Objeto>{new Objeto{atributo1="Dato1", atributo2 = "Dato2"}};
List<Objeto> list2 = new List<Objeto>
{
    new Objeto{atributo1="Dato1", atributo2 = "Dato2"},
    new Objeto{atributo1="Dato3", atributo2 = "Dato4"}
};

//Get the unión between both lists
var listaDefinitiva = list1.Union(list2);

foreach (var objeto in listaDefinitiva)
{
    Console.WriteLine("Atributo1: {0}\t Atributo2: {1}",objeto.atributo1,objeto.atributo2);
}

Выход консоли будет

Atributo1: Dato1         Atributo2: Dato2
Atributo1: Dato3         Atributo2: Dato4
0 голосов
/ 29 марта 2019

Вы можете проверить эту ссылку , и, в частности, следующие примеры:

int[] ints1 = { 5, 3, 9, 7, 5, 9, 3, 7 };
int[] ints2 = { 8, 3, 6, 4, 4, 9, 1, 0 };

IEnumerable<int> union = ints1.Union(ints2);

и это

List<int> ages = new List<int> { 21, 46, 46, 55, 17, 21, 55, 55 };

IEnumerable<int> distinctAges = ages.Distinct();

Просто убедитесь, что вы импортируете System.Linq

using System.Linq
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...