Как я могу выбрать одну запись вместо другой?

У меня есть список, в котором есть дубликаты.

Row#    Lineid  ItemDescItemId  RoadTax VehicleId   Amount
1   122317  None    -1  26.63   -78603  300
2   122317  None    -2  17.75   -78603  200
3   122317  None    -1  22.19   -78602  250
4   122317  Deli    -2  17.75   -78603  200

В этом случае строка 2 является копией строки 4, поскольку совпадают LineId, RoadTax, Amount и VehicleId. Однако я хочу сохранить строку с описанием элемента и исключить строку №2. Итак, мой выходной список выглядит так:

Row#    Lineid  ItemDesc ItemId RoadTax VehicleId   Amount
1   122317  None    -1  26.63   -78603  300
3   122317  None    -1  22.19   -78602  250
4   122317  Deli    -2  17.75   -78603  200

Я написал класс IEqualityComparer на основе примера в MSDN. Класс выглядит так:

  public class RoadTaxComparer : IEqualityComparer<RoadTaxDto>
        {
            // Items are equal if ItemId / VehicleId / RoadTax are equal.
            public bool Equals(RoadTaxDto x, RoadTaxDto y)
            {

                //Check whether the compared objects reference the same data. 
                if (Object.ReferenceEquals(x, y)) return true;

                //Check whether any of the compared objects is null. 
                if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
                    return false;

                //Check whether the products' properties are equal. 
                return x.VehicleId == y.VehicleId && x.ItemId == y.ItemId && x.RoadTax == y.RoadTax && x.Amount == y.Amount;
            }

            // If Equals() returns true for a pair of objects  
            // then GetHashCode() must return the same value for these objects. 

            public int GetHashCode(RoadTaxDto roadTaxDto)
            {
                //Check whether the object is null 
                if (Object.ReferenceEquals(roadTaxDto, null)) return 0;

                //Get hash code for the VehicleId. 
                int hashVehicleId = roadTaxDto.VehicleId.GetHashCode();

                //Get hash code for the ItemId field. 
                int hashCodeItemId = roadTaxDto.ItemId.GetHashCode();

                //Calculate the hash code for the QuoteTaxDto. 
                return hashVehicleId ^ hashCodeItemId;
            }

        }

Структура RoadTaxDto выглядит так:

class RoadTaxDto
{
public int LineId {get;set}
public string ItemDesc {get;set;}
public int VehicleId {get;set;}
public decimal RoadTax {get;set;}
public int VehicleId {get;set;}
public decimal Amount {get;set;}
}

Я использую следующую команду для удаления дубликатов.

List<RoadTaxDto> mergedList = RoadTaxes.Union(RoadTaxes, new RoadTaxComparer()).ToList();

Когда я запускаю на нем компаратор, мне не гарантируется, что строка 2 будет удалена. Итак, как я могу гарантировать, что если у записи есть дубликат, запись с надписью «Нет» всегда будет исключена из списка.


person abhi    schedule 02.08.2013    source источник


Ответы (2)


Чистый "SQLish" подход вам не подходит?

Что-то вроде этого:

var list = new [] { 
    new RoadTaxDto {LineId=122317,ItemDesc="None", ItemId=-1,RoadTax =26.63M  , VehicleId=-78603  ,Amount=300},
    new RoadTaxDto {LineId=122317,ItemDesc="None", ItemId=-2,RoadTax =17.75M  , VehicleId=-78603  ,Amount=200},
    new RoadTaxDto {LineId=122317,ItemDesc="None", ItemId=-1,RoadTax =22.19M  , VehicleId=-78602  ,Amount=250},
    new RoadTaxDto {LineId=122317,ItemDesc="Deli", ItemId=-2,RoadTax =17.75M , VehicleId=-78603  ,Amount=200}
};

var query = (from c in list join x in list 
    on new { c.LineId, c.ItemId , c.VehicleId, c.Amount,c.RoadTax} 
equals new {x.LineId, x.ItemId, x.VehicleId,x.Amount,x.RoadTax}
select new RoadTaxDto {
   LineId = c.LineId,
   ItemDesc = x.ItemDesc!="None"? x.ItemDesc:c.ItemDesc,
   VehicleId=c.VehicleId,
   Amount=c.Amount,
   RoadTax=c.RoadTax,
   ItemId=c.ItemId
}
).GroupBy(x => new { x.LineId, x.RoadTax, x.Amount, x.VehicleId} )
 .Select(grp => grp.Last());

Печать:

LineId  ItemDesc    VehicleId   ItemId  RoadTax Amount
122317  None        -78603      -1      26.63   300
122317  Deli        -78603      -2      17.75   200
122317  None        -78602      -1      22.19   250
person Icarus    schedule 02.08.2013
comment
При таком подходе мне пришлось бы избавиться от RoadTaxComparer, но это работает. Благодарю вас! - person abhi; 02.08.2013

Я бы переместил GetHashCode () в RoadTaxDto, а затем сделал бы следующее:

foreach (var g in list.GroupBy(i => i.GetHashCode()))
    list2.Add(
        g.FirstOrDefault(i => i.ItemDesc != "None") ?? 
        g.First());
person Marek Toman    schedule 02.08.2013
comment
Это интересный подход. Я попробую и дам вам знать. - person abhi; 02.08.2013