使用linq规范对象
本文关键字:对象 范对象 linq 使用 | 更新日期: 2023-09-27 18:02:43
我有一个具有这些属性的IEnumerable<RuleSelection>
:
public class RuleSelection{
public int RuleId { get; set;}
public int? CriteriaId { get; set; }
public int? CriteriaSourceId{ get; set; }
}
RuleSelection
中的RuleId
不是唯一的
我可以写一个linq查询将这些规范化为IEnumerable<Rule>
,这将是:
public class Rule{
public int RuleId { get; set; }
public IEnumerable<int> Criteria { get; set; }
public IEnumerable<int> CriteriaSource { get; set; }
}
Rule.RuleId
将是唯一的,属性Criteria
和CriteriaSource
将分别包括RuleId
的所有CriteriaId
和CriteriaSourceId
。
听起来你想要这样做:
var rules = selections.GroupBy(rs => rs.RuleId)
.Select(g => new Rule {
RuleId = g.Key,
Criteria = g.Select(rs => rs.CriteriaId)
.Where(c => c != null)
.Select(c => c.Value)
.ToList(),
CriteriaSource = g.Select(rs => rs.CriteriaSourceId)
.Where(c => c != null)
.Select(c => c.Value)
.ToList(),
});
使用我的fullloutergroupjoin扩展方法
- LINQ - Full Outer Join
你可以:
theRules.FullOuterGroupJoin(theRules,
r => r.RuleId,
r => r.RuleId,
(crit, critSource, id) => new Rule {
RuleId = id,
Criteria = crit
.Where(r => r.CriteriaId.HasValue)
.Select(r => r.CriteriaId.Value),
CriteriaSource = critSource
.Where(r => r.CriteriaSourceId.HasValue)
.Select(r => r.CriteriaSourceId.Value),
}
);
这样写:
var rules =
from sel in selections
group sel by sel.RuleId into rg
select new Rule {
RuleId = rg.Key,
Criteria = rg.Select(r => r.CriteriaId).FilterValues(),
CriteriaSource = rg.Select(r => r.CriteriaSourceId).FilterValues(),
};
我创建了以下FilterValues
扩展(以消除重复):
public static IEnumerable<T> FilterValues<T>(
this IEnumerable<T?> items)
where T : struct
{
// omitting argument validation
return
from item in items
where item.HasValue
select item.Value;
}
我打算提供一个纯粹的查询语法版本的JonSkeet的答案。我放弃了在努力消除重复的属性分配,并结束了这个组合扩展&查询语法方法。