Linq:在进行投影时设置属性

Posted

技术标签:

【中文标题】Linq:在进行投影时设置属性【英文标题】:Linq: set a property while doing a projection 【发布时间】:2017-12-15 16:09:01 【问题描述】:

我正在做一个简单的 GroupBy 获取第一个元素,但我想修改每个结果的一个属性。

class M

 public string Name get; set;
 public int NOfPeopleWithTheSameName get; set;
 public string P1 get; set;
 public string P2 get; set;
 public string P3 get; set;
 public string P4 get; set;
 public string P5 get; set;
  


List<M> myList = GetMyList();


var l2 = myList
   .GroupBy(m => m.Name)
   .Select(group => new M  Name = group.Key, NOfPeopleWithTheSameName = group.Count() );

这很简单,但如果类有很多属性(因为每个属性值都应该复制到新的属性值),这种方法不是最好的吗?我应该一个一个地复制它们。

我想简单地获取元素并更改属性 NOfPeopleWithTheSameName

【问题讨论】:

这取决于您是否想要新的 M 对象,或者您是否可以改变现有的对象。 你是说myListM类型的列表吗? 是的,myList 的类型是 M 另一种选择是在M 上创建一个构造函数,它接受一个M 对象并为您进行复制,然后您只需更新一个属性。或者查看像 Automapper 这样的映射库。 问题是你的类存储了更多的东西。它不应该知道不属于此类的任何其他集合中有多少重复项。 NOfPeopleWithTheSameName 不属于此类。删除它,你也解决了你的问题,因为你不需要创建它的新实例。 【参考方案1】:

你不需要创建一个新的M,你可以返回现有的,例如:

var l2 = myList
   .GroupBy(m => m.Name)
   .Select(group => 
   
        var m = group.First();
        m.NOfPeopleWithTheSameName = group.Count();
        return m;
   );

但是,如果您打算为此添加一个属性到您的模型中,我建议您使用一个不同的类来包装初始模型和计数 - 不要污染您的模型。例如,你可以有一个像这样的通用包装类:

public class ModelCount<T>

    public T Model  get; set; 
    public int Count  get; set; 

现在像这样分组:

var l2 = myList
   .GroupBy(m => m.Name)
   .Select(group => new ModelCount<M> 
   
        Model = group.First(),
        Count = group.Count()
   );

【讨论】:

@TimSchmelter:我会编辑这个问题。我在示例中添加了 5 个属性。如果只有几个属性但有 7 个或更多属性,则初始化一个新对象以更改单个属性的值可能是有意义的...... @Revious Downvotes 很好,我不关心代表,但我确实想知道我的帖子有什么问题。我要么修复它们,要么删除它们,冷静地不同意,让投票保持不变。不需要有人发表评论,我明白为什么大多数人不评论。 @Revious 一点也不,没有解释的反对票是完全没有评论的,我想要一个。 让我们continue this discussion in chat。【参考方案2】:

是的,你可以...

class Test 

    public string Name  get; set; 
    public int Number  get; set; 


var tests = new List<Test>  /* ... your data here ... */ ;

var modifiedTests = tests.Select(test =>  test.Name = "MODIFIED"; return test; );

// this actually executes above query and modifies your original items in the list:
var modifiedMaterialized = modifiedTests.ToList();

但你真的,真的(!)不应该!

LinQ 是语言集成的查询。有副作用的查询是邪恶的。胡子扭邪。只是不要,你会为自己省去很多痛苦。


我认为您想要的不是 LinQ,而是常规循环:

class M

 public string Name get; set;
 public int NOfPeopleWithTheSameName get; set;
 public string P1 get; set;
 public string P2 get; set;
 public string P3 get; set;
 public string P4 get; set;
 public string P5 get; set;
  

List<M> myList = GetMyList();

var groups = myList.GroupBy(m => m.Name).ToList();

foreach(var group in groups)

    foreach(var member in group)
    
        member.NOfPeopleWithTheSameName = group.Count();
    

【讨论】:

谢谢!是否可以与 GroupBy 的计数相结合? @Revious 也许它可以......但你不应该。更新数据是常规循环的工作。只写一个。 亲爱的投票者,不留下评论什么要改进,很难改进任何东西。随意留下一些建设性的 cmets,这样您就不会白白浪费您的互联网积分。 @DavidG 是的,看起来格林奇就在附近的某个地方:)

以上是关于Linq:在进行投影时设置属性的主要内容,如果未能解决你的问题,请参考以下文章

在linq查询中以匿名类型设置动态对象的所有属性

实体框架 linq 主细节投影到自定义类

为啥在将 First() 应用于投影时,此 linq 代码会以指数方式变慢?

arcmap加载地图以后上下偏移

LINQ查询表达式 - LINQ 查询分组

用css怎么设置字体的投影,用div+css能不能做出投影的效果,好像没有这个属性FILTER。朋友们能不能帮我解