Linq:进行投影时设置属性[英] Linq: set a property while doing a projection

本文是小编为大家收集整理的关于Linq:进行投影时设置属性的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我正在做一个简单的群体,但我想修改每个结果的属性之一.

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,例如:

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

其他推荐答案

是的,您 can ...

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

本文地址:https://www.itbaoku.cn/post/1556959.html

问题描述

I'm doing a simple GroupBy taking the First element but I want to modify one of the property of each result.

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

This is pretty easy, but this way is not the best if the class has many properties (since every property value should be copied to the new one)? I should copy them one by one.

I would like to simply take the element and change the property NOfPeopleWithTheSameName

推荐答案

You don't need to create a new M, you can return the existing one, for example:

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

However, if you are going to add a property to your model just for this, I would suggest instead having a different class that wraps the initial model and the count - don't pollute your models. For example, you could have a generic wrapper class like this:

public class ModelCount<T>
{
    public T Model { get; set; }
    public int Count { get; set; }
}

And now group like this:

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

其他推荐答案

Yes, you can...

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

But you really, really(!) should not!

LinQ is language integrated query. Having a query with side effects is evil. Mustache twisting evil. Just don't, you will save yourself a lot of pain.


I think what you want is just not LinQ, but regular loops:

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