英文:
LINQ Group by doesn't return the result as expected
问题
我有一个动物类:
public class Animals
{
public string Type { get; set; }
public string Gender { get; set; }
public int Amount { get; set; }
}
以及一个与不同动物相关的成本类:
public class Cost
{
public string AnimalType { get; set; }
public int Cost { get; set; }
}
我有一个不同类的列表:
List<Animals> animalList = new List<Animals>()
{
new Animals() { Type = "Wolf", Gender = "Female", Amount = 10 },
new Animals() { Type = "Wolf", Gender = "Male", Amount = 20 },
new Animals() { Type = "Lion", Gender = "Female", Amount = 10 },
new Animals() { Type = "Horse", Gender = "Male", Amount = 5 }
};
List<Cost> cost = new List<Cost>()
{
new Cost() { AnimalType = "Wolf", Cost = 1000 },
new Cost() { AnimalType = "Lion", Cost = 2000 },
new Cost() { AnimalType = "Horse", Cost = 1500 }
}
我想对每种动物的成本进行求和,得到如下结果:
AnimalType | Cost |
---|---|
Wolf | 30000 |
Lion | 20000 |
Horse | 7500 |
我尝试使用 LINQ 和如下方式进行求和:
var totalCost = from animal in animalList
join cost in costList
on animal.Type equals cost.AnimalType
group animal by animal.Type into g
select g;
但这只返回了 Wolf(可能是因为它是唯一有两种性别的动物),但我不明白为什么。我该如何编写 select
来找到我想要的结果?
英文:
I have an animal class:
public class Animals
{
public string Type { get; set; }
public string Gender { get; set; }
public int Amount { get; set; }
}
and a class Cost for the cost associated with the different animals:
public class Cost
{
public string AnimalType { get; set; }
public int Cost { get; set; }
}
I have a list of the different classes:
List<Animals> animalList = new List<Animals>()
{
new Animals() { Type = "Wolf", Gender = "Female", Amount = 10 },
new Animals() { Type = "Wolf", Gender = "Male", Amount = 20 },
new Animals() { Type = "Lion", Gender = "Female", Amount = 10 },
new Animals() { Type = "Horse", Gender = "Male", Amount = 5 }
};
List<Cost> cost = new List<Cost>()
{
new Cost() { AnimalType = "Wolf", Cost = 1000 },
new Cost() { AnimalType = "Lion", Cost = 2000 },
new Cost() { AnimalType = "Horse", Cost = 1500 }
}
I want to sum the cost for each animals having a result like this:
AnimalType | Cost |
---|---|
Wolf | 30000 |
Lion | 20000 |
Horse | 7500 |
I've tried to use LINQ and sum like this:
var totalCost = from animal in animalList
join cost in costList
on animal.Type equals cost.AnimalType
group animal by animal.Type into g
select g;
but this only returns Wolf (supposedly because it is the only one having two genders), but I don't understand why. How can I write the select
to find what I am looking for?
答案1
得分: 5
问题是您当前的LINQ查询返回了animal
数据(g
)。
相反,在分组时,应构建一个包含animal
和cost
数据的新数据集,以便您可以在投影中执行计算。
List<CostModel> costList = new List<CostModel>()
{
new CostModel() { AnimalType = "Wolf", Cost = 1000 },
new CostModel() { AnimalType = "Lion", Cost = 2000 },
new CostModel() { AnimalType = "Horse", Cost = 1500 }
};
var totalCost = (from animal in animalList
join cost in costList
on animal.Type equals cost.AnimalType
group new { Animal = animal, Cost = cost } by animal.Type into g
select new
{
AnimalType = g.Key,
Cost = g.Sum(x => x.Cost.Cost * x.Animal.Amount)
}).ToList();
public class CostModel
{
public string AnimalType { get; set; }
public int Cost { get; set; }
}
尽管您的代码中存在一些错误:
-
在LINQ查询中,使用了
join cost in costList
,但没有声明costList
变量。 -
Cost
类中将出现错误,因为有一个与类名冲突的Cost
属性。
英文:
The problem is your current LINQ query returns the animal
data (g
).
Instead, when grouping, a new dataset containing animal
and cost
data should be constructed in order to allow you to perform the calculation in projection.
List<CostModel> costList = new List<CostModel>()
{
new CostModel() { AnimalType = "Wolf", Cost = 1000 },
new CostModel() { AnimalType = "Lion", Cost = 2000 },
new CostModel() { AnimalType = "Horse", Cost = 1500 }
};
var totalCost = (from animal in animalList
join cost in costList
on animal.Type equals cost.AnimalType
group new { Animal = animal, Cost = cost } by animal.Type into g
select new
{
AnimalType = g.Key,
Cost = g.Sum(x => x.Cost.Cost * x.Animal.Amount)
}).ToList();
public class CostModel
{
public string AnimalType { get; set; }
public int Cost { get; set; }
}
While there are few errors in your code:
-
In the LINQ query,
join cost in costList
but there is no declaration for thecostList
variable. -
You will get error in
Cost
class as there isCost
property which clash the class name.
答案2
得分: 1
也许使用一个成本的字典会更好:
Dictionary<string, int> cost = new Dictionary<string, int>()
{
{"Wolf", 1000 },
{"Lion", 2000 },
{ "Horse", 1500 }
};
然后你可以使用以下的LINQ查询:
var result = animalList
.GroupBy(x => x.Type)
.Select(x => new { AnimalType = x.Key, Amount = cost[x.Key] * x.Sum(y => y.Amount)})
.ToList();
请注意,如果动物类型中的某个不在字典中,该代码将引发异常。如果你不想要异常,你也可以插入一个条件:
var result = animalList
.Where(x => cost.ContainsKey(x.Type))
.GroupBy(x => x.Type)
.Select(x => new { AnimalType = x.Key, Amount = cost[x.Key] * x.Sum(y => y.Amount)})
.ToList();
在线演示:https://dotnetfiddle.net/B5gOaG
英文:
Maybe a dictionary for the cost would be better:
Dictionary<string,int> cost = new Dictionary<string,int> ()
{
{"Wolf", 1000 },
{"Lion", 2000 },
{ "Horse", 1500 }
};
Then you can use the following LINQ query:
var result = animalList
.GroupBy(x => x.Type)
.Select(x => new { AnimalType = x.Key, Amount = cost[x.Key] * x.Sum(y => y.Amount)})
.ToList();
Note that the code will throw an exception if one of the animal types is not in the dictionary. If you don't want that, you can also insert a where clause:
var result = animalList
.Where(x => cost.ContainsKey(x.Type))
.GroupBy(x => x.Type)
.Select(x => new { AnimalType = x.Key, Amount = cost[x.Key] * x.Sum(y => y.Amount)})
.ToList();
Online-demo: https://dotnetfiddle.net/B5gOaG
答案3
得分: -1
-
根据您的代码,您需要更改 Cost 类中的属性名称 Cost。
(我将其更改为 cost) -
创建一个名为 CostModel 的新类。
public class CostModel
{
public string Animal { get; set; }
public int Cost { get; set; }
}
- 尝试这段代码
var totalCost = (from animal in animalList
join cost in costList
on animal.Type equals cost.AnimalType
group new { Animal = animal, Cost = cost }
by animal.Type into g
select new CostModel
{
Animal = g.Key,
Cost = g.Sum(x => x.Cost.cost * x.Animal.Amount)
}).ToList();
foreach(var cost in totalCost)
{
Console.WriteLine(cost.Animal.ToString() + ":" + cost.Cost);
}
英文:
-
As per your code, you have to change the property name Cost in Cost class.
(I changed it into cost) -
Create new class as CostModel.
public class CostModel
{
public string Animal { get; set; }
public int Cost { get; set; }
}
- Try this code
var totalCost = (from animal in animalList
join cost in costList
on animal.Type equals cost.AnimalType
group new { Animal = animal, Cost = cost }
by animal.Type into g
select new CostModel
{
Animal = g.Key,
Cost = g.Sum(x => x.Cost.cost * x.Animal.Amount)
}).ToList();
foreach(var cost in totalCost)
{
Console.WriteLine(cost.Animal.ToString() + ":" + cost.Cost);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论