使用linq标准化对象

时间:2013-03-06 22:36:14

标签: c# linq

我有IEnumerable<RuleSelection>这些属性:

public class RuleSelection{
  public int RuleId { get; set;}
  public int? CriteriaId { get; set; }
  public int? CriteriaSourceId{ get; set; }
}
<{1}}中的{p> RuleId并非唯一。

我是否可以编写一个linq查询来将这些规范标准化为RuleSelection,这将是:

IEnumerable<Rule>

public class Rule{ public int RuleId { get; set; } public IEnumerable<int> Criteria { get; set; } public IEnumerable<int> CriteriaSource { get; set; } } 将是唯一的,属性Rule.RuleIdCriteria将包含{{1}的所有CriteriaSourceCriteriaId分别。

3 个答案:

答案 0 :(得分:10)

听起来你想要这样的东西:

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

答案 1 :(得分:0)

使用我的FullOuterGroupJoin扩展方法

你可以:

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

答案 2 :(得分:0)

写这个:

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的答案。我放弃了这一点,努力消除财产分配的重复,并结束了这个组合扩展&amp;查询语法方法。