2
votes

Supprimer la valeur en double de la liste

J'ai une liste qui contient des données et parfois elle contient des lignes en double et je veux supprimer cette ligne en double pour celle que j'ai utilisée ci-dessous le code

num = numDetailsTemp.Distinct().ToList();
var query = num.GroupBy(o => new { o.Number })
                                  .Select(group =>
                                        new
                                        {
                                            Name = group.Key,
                                            Numbers = group.OrderByDescending(x => x.Date)
                                        })
                                  .OrderBy(group => group.Numbers.First().Date);
                            List<NumberDetails> numTemp = new List<NumberDetails>();

                            foreach (var group in query)
                            {
                                foreach (var numb in group.Numbers)
                                {
                                    numTemp.Add(numb);
                                    break;
                                }
                            }
                            num = numTemp;

L'image ci-dessous montre la valeur en double du list.

 entrez la description de l'image ici

Et quand j'applique supprimer les doublons, cela me donne une sortie

entrer l'image description here

Mais je veux supprimer cette ligne qui ne contient pas d'alter no ou de preuve d'identité et de date comme indiqué dans la première image, première ligne non, contient AlterNo et ID preuve et date et la deuxième ligne contient cela, donc je veux supprimer la première ligne et n'afficher que la deuxième ligne. La date est obligatoire pour vérifier et après cela AlterNo et preuve d'identité.


0 commentaires

3 Réponses :


1
votes

Vous pouvez éliminer les doublons en utilisant l'opérateur Distinct . Vous devez d'abord définir une classe de comparateur qui implémente l'interface IEqualityComparer , puis la transmettre à l'opérateur distinct de votre méthode.

var distinctRecords = source.Distinct(new NumberDetailsComparer());

Et voici comment l'utiliser :

internal class NumberDetailsComparer : IEqualityComparer<NumberDetails>
{
    public bool Equals(NumberDetails x, NumberDetails y)
    {
        if (\* Set of conditions for equality matching *\)
        {
            return true;
        }
        return false;
    }

    public int GetHashCode(Student obj)
    {
        return obj.Name.GetHashCode(); // Name or whatever unique property
    }
} 

Tout ce que vous avez à faire est de définir les critères de la classe de comparaison. J'espère que cela résout votre problème.

Ce lien pourrait être utile pour un exemple pleinement fonctionnel:

http://dotnetpattern.com/linq-distinct-operator


2 commentaires

Ma liste contient uniquement des données distinctes


distinct est un terme relatif, vous dans la classe de comparaison devez lui dire ce qui est distinct. dans votre cas, les enregistrements qui n'ont pas de valeur pour les champs mentionnés ne doivent pas être choisis.



2
votes

Vous pouvez essayer ce qui suit:

var group = 
    list
    .GroupBy(r => r.Number)
    .SelectMany(g => g) //flatten your grouping and filter where you have alterno and id
    .Where(r => !string.IsNullOrEmpty(r.AlterNo) && !string.IsNullOrEmpty(r.Id))
    .OrderByDescending(r=>r.Date)
    .ToList();


4 commentaires

Je veux une date aussi parce que le principal est la date, puis l'alteno et la preuve d'identité


Votre question ne précise pas cela ainsi que l'image que vous avez publiée. Mettez à jour votre question pour la rendre plus claire.


Votre image montre que les deux lignes ont des dates. Que voulez-vous exactement? Les 3 champs doivent-ils être présents pour être choisis?


Oui, je compare la date car je veux une date récente et non la date précédente.Si les enregistrements en double ont la même date, comparez la preuve d'identité et AlterNo et supprimez ceux qui ne contiennent pas de preuve d'identité et Alterno



0
votes

Vous avez donc une séquence de NumberDetails , et une définition du moment où vous considérez que NumberDetails est égal.

Une fois que vous avez trouvé quel NumberDetails sont égaux, vous souhaitez éliminer les doublons, sauf un: un duplicata qui a des valeurs pour AlterNo et IdProof.

Hélas vous ne l'avez pas fait ne spécifiez pas ce que vous voulez s'il n'y a pas de doublons avec des valeurs pour AlterNo et IdProof . Ni ce que vous voulez s'il y a plusieurs doublons avec des valeurs pour AlterNo et IdProof.

Mais supposons que s'il y a plusieurs de ces éléments, vous s'en fout: choisissez-en un, car ce sont des doublons de toute façon.

Dans votre exigence, vous parlez de doublons. Alors écrivons une classe qui implémente vos exigences d'égalité:

var groupsEqualNumberDetails = numberDetails.GroupBy(

    // keySelector: make groups with equal NumberDetails:
    numberDetail => numberDetail,

    // ResultSelector: take the key and all NumberDetails thas equal this key:
    // and keep the first one that has values for AlterNo and IdProof
    (key, numberDetailsEqualToKey) => numberDetailsEqualToKey
          .Where(numberDetail => numberDetail.AlterNo != null
                              && numberDetail.IdProof != null)
          .FirstOrDefault(),

    // KeyComparer: when do you consider two NumberDetails equal?
    NumberDetailEqualityComparer.Default;
}

Vous devez également implémenter GetHashCode. Vous pouvez retourner tout ce que vous voulez, tant que vous sont certains que si x et y sont égaux, ils renvoient le même HashCode De plus, il serait plus efficace que si x et y ne sont pas égaux, alors il y a une forte probabilité pour un HashCode différent.

Quelque chose comme:

public int GetHashCode(NumberDetail numberDetail)
{
    const int prime1 = 12654365;
    const int prime2 = 54655549;

    if (numberDetail == null) return prime1;

    int hash = prime1;
    unsafe
    {
        hash = prime2 * hash + numberDetail.Number.GetHashCode();
        hash = prime2 * hash + numberDetail.FullName.GetHashCode();
        hash = prime2 * hash + numberDetail.Date.GetHashCode();
        ...
    }
    return hash;

Bien sûr, vous devez vérifier si l'une des propriétés est égale à NULL avant de demander le HashCode.

Évidemment dans votre égalité (et donc dans GetHashCode) vous ne regardez ni AlterNo ni IdProof .

Une fois que vous avez défini précisément lorsque vous considérez deux NumberDetails égaux, vous pouvez créer des groupes de NumberDetails

class NumberDetailEqualityComparer : IEqualityComparer<NumberDetail>
{
    public static IEQualityComparer<NumberDetail> Default {get;} = new NumberDetaulEqualityComparer();

    public bool Equals(NumberDetail x, NumberDetail y)
    {
         if (x == null) return y == null;              // true if both null
         if (y == null) return false;                  // because x not null and y null
         if (Object.ReferenceEquals(x, y) return true; // because same object
         if (x.GetType() != y.GetType()) return false; // because not same type

         // by now we are out of quick checks, we need a value check
         return x.Number == y.Number
             && x.FullName == y.FullName
             && ...
             // etc, such that this returns true if according your definition
             // x and y are equal
    }

p>


0 commentaires