2013-12-16 45 views
1

我有对象的列表如下所述:得到对象列表和在LINQ C#

List<Maths> mObjs = new List<Maths>(); 
mObjs.Add(new Maths{ Name = "Jack", M1 = 10, M2 = 5, M3 = 0, M4 = 2, M5 =1 }); 
mObjs.Add(new Maths { Name = "Jill", M1 = 2, M2 = 3, M3 = 4, M4 = 1, M5 = 0 }); 
mObjs.Add(new Maths { Name = "Michel", M1 = 12, M2 = 15, M3 = 10, M4 = 12, M5 = 11 }); 

现在我需要计算所有三个人的总聚合值。 我需要得到下面的结果,可能是一个新的其他类

List<Results> mRes = new List<Results>(); 

public class Results{ 
    public string Name { get; set; } 
    public int TotalValue { get; set; } 

} 

mRes.Name = "M1" 
mRes.TotalValue = 24; 

mRes.Name = "M2" 
mRes.TotalValue = 23; 

mRes.Name = "M3" 
mRes.TotalValue = 14; 

mRes.Name = "M4" 
mRes.TotalValue = 15; 


mRes.Name = "M5" 
mRes.TotalValue = 12; 

有人能告诉我如何可以从使用LINQ查询mObjs这个数据? 我知道我们可以使用for,但想知道是否有更好的方法来使用linq查询,因为这会减少代码行,并且在许多其他地方也有类似的需求,并且不想编写foreach或每次都有。

请帮忙??

回答

4

您可以使用预先选择列表中列出的名称和领域选择

var lookups = new Dictionary<string,Func<Maths,int>> { 
    {"M1", x => x.M1 }, 
    {"M2", x => x.M2 }, 
    {"M3", x => x.M3 }, 
    {"M4", x => x.M4 }, 
    {"M5", x => x.M5 }, 
}; 

然后,你可以简单地做

var mRes = dlookups.Select(x => new Results { 
               Name= x.Key, 
               TotalValue = mObjs.Sum(x.Value) 
          }).ToList(); 

BEGIN修订版*

回应评论

lambda表达式只是从源类到int的一个函数。

例如

class Sub1 { 
    string M3 {get;set;} 
    int M4 {get;set;} 
} 

class Math2 { 
    string Name {get;set;} 
    string M1 {get;set;} 
    string M2 {get;set;} 
    Sub1 Sub {get;set;} 
} 

var lookups = new Dictionary<string,Func<Math2,int>> { 
    { "M1", x => int.Parse(x.M1) }, 
    { "M2", x => int.Parse(x.M2) }, 
    { "M3", x => int.Parse(x.Sub.M3) }, 
    { "M4", x => int.Parse(x.Sub.M4} } 
}; 

或者,如果你想放一点错误检查中,您可以使用的功能或嵌入代码。如果你想走得更远,你可以使用反射来构建查找字典

int GetInt(string source) { 
    if (source == null) return 0; 
    int result; 
    return int.TryParse(source, out result) ? result : 0; 
} 

var lookups = new Dictionary<string,Func<Math2,int>> { 
    { "M1", x => { 
        int result; 
        return x == null ? 0 : (int.TryParse(x,out result) ? result : 0); 
       }, 
    { "M2", x => GetInt(x) }, 
    { "M3", x => x.Sub == null ? 0 : GetInt(x.Sub.M3) }, 
    { "M4", x => x.Sub == null ? 0 : x.Sub.M4} 
}; 

结束时更新

这是一个帮助函数,它将生成一个类的所有Integer属性的查找。

public Dictionary<string,Func<T,int>> GenerateLookups<T>() where T: class { 
    // This just looks for int properties, you could add your own filter 
var properties = typeof(T).GetProperties().Where(pi => pi.PropertyType == typeof(int)); 

var parameter = Expression.Parameter(typeof(T)); 

    return properties.Select(x => new { 
    Key = x.Name, 
    Value = Expression.Lambda<Func<T,int>>(Expression.Property(parameter,x),parameter).Compile() 
    }).ToDictionary (x => x.Key, x => x.Value); 

} 

现在,你可以这样做:

var mRes=GenerateLookups<Maths>().Select(x => new Results 
    { 
    Name = x.Key, 
    TotalValue = mObjs.Sum(x.Value) 
    }).ToList(); 
+0

感谢这..im试..我回来 – mmssaann

+0

绝对辉煌..非常感谢.. – mmssaann

+0

在这里面临的小问题。在其他类中,点存储在字符串变量中。我怎样才能将该字符串属性转换为int? – mmssaann

1

不是很聪明,但效率和可读性:

int m1Total= 0; 
int m2Total= 0; 
int m3Total= 0; 
int m4Total= 0; 
int m5Total= 0; 
foreach(Maths m in mObjs) 
{ 
    m1Total += m.M1; 
    m2Total += m.M2; 
    m3Total += m.M3; 
    m4Total += m.M4; 
    m5Total += m.M5; 
} 
List<Results> mRes = new List<Results> 
{ 
    new Results{ Name = "M1", TotalValue = m1Total }, 
    new Results{ Name = "M2", TotalValue = m2Total }, 
    new Results{ Name = "M3", TotalValue = m3Total }, 
    new Results{ Name = "M4", TotalValue = m4Total }, 
    new Results{ Name = "M5", TotalValue = m5Total }, 
}; 

结果:

Name: "M1" TotalValue: 24 
Name: "M2" TotalValue: 23 
Name: "M3" TotalValue: 14 
Name: "M4" TotalValue: 15 
Name: "M5" TotalValue: 12 

编辑:因为你已经明确要求对LINQ,如果属性始终是这五个我不看不出为什么你需要使用LINQ。如果数字可以改变,我会使用不同的结构。

例如,你可以使用

  • 一个List<Measurement>,而不是多个属性的其中Measurement是存储的名称和值的另一个类或者你可以使用
  • 一个Dictionary<string, int>高效查找。
0

你可以尝试一些事情是这样的:

mRes.Add(new Results() { Name = "M1", TotalValue = mObjs.Sum(x => x.M1) }); 

要以编程方式通过所有的类属性循环,您可能需要使用反射。