我有一个对象列表让我们说用户。
public class User
{
public string Name {get;set;}
public string Sex {get;set;}
public DateTime Birthday {get;set;}
public string Type {get;set;}
public string SubType {get;set;}
public int FilterId {get;set;}
}
假设我有以下结果
Josh, M, 5/1/1980, Admin, Main, null
John, M, 5/1/1980, User, Main, null
Jane, F, 5/2/1980, User, Main, null
Josh, M, 5/1/1980, Admin, Main 1
John, M, 5/1/1980, User, Main, null
Josh, M, 5/1/1980, User, Main, null
我想得到以下结果。
Josh, M, 5/1/1980, Admin, Main 1
John, M, 5/1/1980, User, Main, null
Jane, F, 5/2/1980, User, Main, null
Josh, M, 5/1/1980, User, Main, null
重要的是它返回了Josh的记录,其中FilterId不为null。我认为类似于Group By with Order By和firstordefault。
我在编写包含多个字段的groupby子句时遇到问题,并使其正常工作。
修改示例以反映需要成为groupby一部分的其他属性。
答案 0 :(得分:3)
您的' FilterId'永远不能为空,因为它是int
。假设它实际上是int?
又称Nullable<int>
,这将起作用:
IEnumerable<User> users = GetSomeUsers() ;
User[] distinctUsers = users
.GroupBy( x => new Tuple<string,string,DateTime>(x.Name,x.Sex,x.Birthday))
.SelectMany( g => g.OrderBy( x=> x.FilterId.HasValue ? 0 : 1 )
.ThenBy( x => x.FilterId )
.Take(1)
)
.ToArray()
;
此代码
答案 1 :(得分:1)
groupby部分:
.GroupBy(x => new { x.Name , x.Sex, x.Birthday});
从这里开始选择第一个:
.GroupBy(x => new { x.Name , x.Sex, x.Birthday}).Select(y=>x.First());
如果您希望第一个没有null,则可以执行OrderByDescending
.OrderByDescending(usr=>usr.FilterId ).GroupBy(x => new { x.Name , x.Sex, x.Birthday}).Select(y=>y.First()).ToList();
filterId是一个整数。它不能为空
答案 2 :(得分:0)
对多个属性进行分组的最简单方法是使用匿名类型:
var groups = users.GroupBy(user => new
{
Name,
Type,
SubType,
});
这是有效的,因为匿名类型的实现使得它们覆盖Equals
方法以比较该类型的每个成员的值,并且还覆盖GetHashCode
方法以使其成为复合哈希对象的所有值的哈希值。如果你刚刚创建了一个新的命名类型,你需要自己处理所有这些,这简直是单调乏味的。
答案 3 :(得分:-1)
主要的理解是使用IEqualityComparer,类LambdaCustomComparer是一个帮助器,可以动态地使用LINQ来完成。
您需要复制并粘贴此内容:
public class User
{
public string Name { get; set; }
public string Sex { get; set; }
public DateTime Birthday { get; set; }
public int? FilterId { get; set; }
}
public class LambdaCustomComparer<T> : IEqualityComparer<T>
{
private readonly Func<T, T, bool> lambdaComparer;
private readonly Func<T, int> lambdaHash;
public LambdaCustomComparer(Func<T, T, bool> lambdaComparer, bool ignoreHashcode = true)
{
if (lambdaComparer == null)
throw new ArgumentNullException("lambdaComparer");
this.lambdaComparer = lambdaComparer;
if (ignoreHashcode)
lambdaHash = obj => 0;
else
lambdaHash = EqualityComparer<T>.Default.GetHashCode;
}
public LambdaCustomComparer(Func<T, T, bool> lambdaComparer, Func<T, int> lambdaHash)
{
if (lambdaComparer == null)
throw new ArgumentNullException("lambdaComparer");
if (lambdaHash == null)
throw new ArgumentNullException("lambdaHash");
this.lambdaComparer = lambdaComparer;
this.lambdaHash = lambdaHash;
}
public bool Equals(T x, T y)
{
return lambdaComparer(x, y);
}
public int GetHashCode(T obj)
{
return lambdaHash(obj);
}
}
var list = new List<User>
{
new User() {Name = "Josh", Sex= "M", Birthday = DateTime.Now, FilterId = null},
new User() {Name = "John", Sex= "M", Birthday = DateTime.Now, FilterId = null},
new User() {Name = "Jane", Sex= "F", Birthday = DateTime.Now, FilterId = null},
new User() {Name = "Josh", Sex= "M", Birthday = DateTime.Now, FilterId = 1},
new User() {Name = "John", Sex= "M", Birthday = DateTime.Now, FilterId = null},
};
var comparer = new LambdaCustomComparer<User>((a, b) => a.Name == b.Name && a.Birthday.Date == b.Birthday.Date && a.Sex == b.Sex && a.FilterId == b.FilterId);
var distinctList = list.GroupBy(user => user, comparer).ToDictionary(a => a.Key, b => b.ToArray());