Linq加入不平等

时间:2014-04-02 11:22:30

标签: c# linq-to-objects

我有3个班级:

public class HoteAvail
{
    public int HotelID { get; set; }
    public string Name { get; set; }
    public List<Room> Rooms { get; set; }

}

public class Room
{
    public int RoomID { get; set; }
    public string RoomName { get; set; }
}

public class DAL
{

    public static List<HoteAvail> GetAll()
    {
        return new List<HoteAvail>()
        {

           new  HoteAvail{HotelID=1,Name="Taj",Rooms=new List<Room>(){new Room{RoomID=1,RoomName="Deliux"}}},
           new  HoteAvail{HotelID=2,Name="x",Rooms=new List<Room>(){new Room{RoomID=2,RoomName="dd"},new Room{RoomID=1,RoomName="qq"}}},
           new  HoteAvail{HotelID=3,Name="y",Rooms=new List<Room>(){new Room{RoomID=3,RoomName="yy"},new Room{RoomID=1,RoomName="rr"}}},

        };
    }

    public static List<HoteAvail> GetAllII()
    {
        return new List<HoteAvail>()
        {

           new  HoteAvail{HotelID=1,Name="Taj",Rooms=new List<Room>(){new Room{RoomID=1,RoomName="Deliux"},new Room{RoomID=1,RoomName="pp"}}},
           new  HoteAvail{HotelID=4,Name="x",Rooms=new List<Room>(){new Room{RoomID=2,RoomName="dd"},new Room{RoomID=1,RoomName="qq"}}},
           new  HoteAvail{HotelID=5,Name="y",Rooms=new List<Room>(){new Room{RoomID=3,RoomName="yy"},new Room{RoomID=1,RoomName="rr"}}},

        };
    }
}

我想加入DAL.GetAll()和DAL.GetAllII()的值,结果应该只包含那些酒店ID不匹配的值。

最终结果集应该是:

new HoteAvail{HotelID=2,Name="x",Rooms=new List<Room>(){new Room{RoomID=2,RoomName="dd"},new Room{RoomID=1,RoomName="qq"}}},
new HoteAvail{HotelID=3,Name="y",Rooms=new List<Room>(){new Room{RoomID=3,RoomName="yy"},new Room{RoomID=1,RoomName="rr"}}},
new HoteAvail{HotelID=4,Name="x",Rooms=new List<Room>(){new Room{RoomID=2,RoomName="dd"},new Room{RoomID=1,RoomName="qq"}}},
new  HoteAvail{HotelID=5,Name="y",Rooms=new List<Room>(){new Room{RoomID=3,RoomName="yy"},new Room{RoomID=1,RoomName="rr"}}}

我试过了:

var groupBNames = new HashSet<string>(DAL.GetAll().Select(x => x.HotelID.ToString()));
var filteredEmployees = DAL.GetAllII().Where(x => !groupBNames.Contains(x.HotelID.ToString()));

var resultList = from a in DAL.GetAll()
where !(DAL.GetAllII().Any(HotelID => HotelID == a))
    select a;

但我没有取得任何成功。提前谢谢。

2 个答案:

答案 0 :(得分:2)

我建议使用自定义IEqualityComparer做2个例外。您可以使用this method创建比较器:

// create a comparer to compare HotelAvail objects by hotelId
// see http://www.codeducky.org/10-utilities-c-developers-should-know-part-two/
// for the implementation of EqualityComparers.Create, which is a nice shortcut
var comparer = EqualityComparers.Create<HoteAvail>(ha => ha.HotelId); // compare by hotelId

var results = 
    // first take all entries in GetAll() NOT IN GetAllII()
    DAL.GetAll().Except(DAL.GetAllII(), comparer)
        // then add all entries in GetAllII() NOT IN GetAll()
        .Concat(DAL.GetAllII()).Except(DAL.GetAll(), comparer);

答案 1 :(得分:0)

您可以实施自定义IEqualityComparer<HoteAvail>

public class HoteAvailComparer: IEqualityComparer<HoteAvail>
{
    public bool Equals(HoteAvail x, HoteAvail y)
    {
        return x != null && y != null && x.HotelID == y.HotelID;
    }

    public int GetHashCode(HoteAvail obj)
    {
        return obj.HotelID;
    }
}

你可以使用Enumerable.Except这是有效的,因为它使用了一个集合:

var resultList = DAL.GetAll().Except(DAL.GetAllII(), new HoteAvailComparer());
Console.WriteLine(String.Join(",", resultList.Select(h => h.HotelID))); // 2,3

<强>更新

  

它给了我HotelId 2,3,我想加入它的价值观   DAL.GetAll()和DAL.GetAllII()和结果应该只包含那些   酒店ID不匹配的值。结果应该有   HotelId 2,3,4,5

然后你需要从两个角度使用Except

var hotelComparer = new HoteAvailComparer();
var all1 = DAL.GetAll();
var all2 = DAL.GetAllII();
var resultList = all1.Except(all2, hotelComparer).Concat(all2.Except(all1, hotelComparer));

期望的结果2,3,4,5:

Console.WriteLine(String.Join(",", resultList.Select(h => h.HotelID))); 

当然,您也可以使用ConcatGroupBy,但效率和可维护性较低:

resultList = all1.Concat(all2).GroupBy(h => h.HotelID)
    .Where(g => g.Count() == 1)
    .SelectMany(g => g);

您可以将IEqualityComparer<HoteAvail>用于许多其他LINQ方法,例如GroupBy + DistinctJoinIntersect等。

相关问题