【问题标题】:Linq: set a property while doing a projectionLinq:在进行投影时设置属性
【发布时间】: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 不属于此类。删除它,你也解决了你的问题,因为你不需要创建它的新实例。

标签: c# linq


【解决方案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 一点也不,没有解释的反对票是完全没有评论的,我想要一个。
【解决方案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 是的,看起来格林奇就在附近的某个地方:)
猜你喜欢
  • 2015-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-18
相关资源
最近更新 更多