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
对象,或者您是否可以改变现有的对象。
你是说myList
是M
类型的列表吗?
是的,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:在进行投影时设置属性的主要内容,如果未能解决你的问题,请参考以下文章