从List <t>删除重复值

时间:2019-05-25 04:13:13

标签: c# linq

我有一个包含数据的列表,有时它包含重复的行,我想删除我在代码下面使用的重复行

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;

下图显示了列表中的重复值。

enter image description here

当我应用删除重复项时,它会给我输出

enter image description here

但是我要删除不包含alter no或id证明和日期的行,如第一张图片第一行所示,不包含AlterNo和ID证明和日期,而第二行包含该行,因此我要删除第一行并仅显示第二行。日期是必须检查的,之后是AlterNo和ID证明。

3 个答案:

答案 0 :(得分:2)

您可以使用Distinct运算符消除重复项。首先,您需要定义一个实现IEqualityComparer接口的比较器类,然后将其传递给您方法中的不同运算符。

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
    }
} 

这是使用方法:

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

您需要做的就是定义比较器类的条件。 希望这能解决您的问题。

此链接对于完整的示例可能有用:

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

答案 1 :(得分:2)

您可以尝试以下操作:

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();

答案 2 :(得分:0)

因此,您有一个NumberDetails的序列,以及一个有关何时考虑NumberDetails相等的定义。

一旦发现哪个NumberDetails相等,就想消除重复项,但重复项除外:重复项的值分别为AlterNoIdProof

las,如果没有重复的AlterNoIdProof值,则您没有指定所需的内容。如果有多个重复的值分别为AlterNoIdProof的内容,您也不需要什么。

但是让我们假设,如果其中有多个项目,则您不在乎:只需选择一个,因为它们仍然是重复项。

根据您的要求,您谈论重复项。因此,让我们编写一个实现您的平等要求的类:

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
    }

您还需要实现GetHashCode。您可以返回任何您想要的东西,只要您 确定如果x和y相等,则它们返回相同的HashCode 此外,如果x和y不相等,将会更有效率 那么使用不同的HashCode的可能性就很大。

类似的东西:

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;

当然,您必须在询问HashCode之前检查是否有任何属性等于NULL。

很显然,在平等的情况下(因此在GetHashCode中),您不会查看AlterNoIdProof

在精确定义了两个NumberDetails相等的对象后,就可以将相等的NumberDetails组组成

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