分组和单独列表
Group and separate list
我有以下实体结构
public class Item
{
public EnumType Type { get; set; }
public int Price { get; set; }
}
public enum EnumType
{
A =1,
B=2,
C =3
}
我有如下物品清单
var items = new List<Item>
{
new Item{ Price=5, Type= EnumType.B},
new Item{ Price=5, Type= EnumType.B},
new Item{ Price=5, Type= EnumType.B},
new Item{ Price=10, Type= EnumType.B},
new Item{ Price=10, Type= EnumType.B},
new Item{ Price=10, Type= EnumType.B},
new Item{ Price=15, Type= EnumType.C},
new Item{ Price=15, Type= EnumType.C},
new Item{ Price=15, Type= EnumType.C},
new Item{ Price=15, Type= EnumType.C},
new Item{ Price=15, Type= EnumType.C}
};
如果价格和类型相同,则需要根据类型从列表中排除每第n项,然后计算总和。
即类型 B = 3,类型 C = 4
这意味着在上面的示例数据中,由于类型 B 中有 3 个项目,一旦按价格和类型分组,因此在计算总和时需要排除每第 3 个项目。
所以类型 B 的总和将为 5+5+10+10,类型 C 的总和将为 15+15+15+15
我试过使用模块化,但似乎方向不对
到目前为止我已经试过了
static int GetFactorByType(EnumType t)
{
switch(t)
{
case EnumType.A:
return 2;
case EnumType.B:
return 3;
case EnumType.C:
return 4;
default:
return 2;
}
}
var grp = items.GroupBy(g => new { g.Type, g.Price }).Select(s => new
{
type= s.Key.Type,
price = s.Key.Price,
count = s.Count()
}).Where(d => d.count % GetFactorByType(d.type) == 0).ToList();
按始终唯一的新对象分组可保证您拥有的组数与项目数一样多。尝试这样的事情:
var grp = items.GroupBy(g => $"{g.Type}/{g.Price}").Select(s => new
{
type= s.Value.First().Type,
price = s.Value.First().Price,
count = s.Value.Count()
}).Where(d => count % GetFactorByType(d.type) == 0).ToList();
这样,您按 type/price 组合组成的字符串进行分组,因此如果项目相等,则字符串将相等。
对于您的前三个项目示例,$"{g.Type}/{g.Price}"
字符串相当于 "B/5"
,因此它也非常可读。
这是一个解决方法:
//track the type:nth element discard
var dict = new Dictionary<EnumType, int?>();
dict[EnumType.B] = 3;
dict[EnumType.C] = 4;
//groupby turns our list of items into two collections, depending on whether their type is b or c
var x = items.GroupBy(g => new { g.Type })
.Select(g => new //now project a new collection
{
g.Key.Type, //that has the type
SumPriceWithoutNthElement = //and a sum
//the sum is calculated by reducing the list based on index position: in where(v,i), the i is the index of the item.
//We drop every Nth one, N being determined by a dictioary lookup or 2 if the lookup is null
//we only want list items where (index%N != N-1) is true
g.Where((v, i) => (i % (dict[g.Key.Type]??2)) != ((dict[g.Key.Type] ?? 2) - 1))
.Sum(r => r.Price) //sum the price for the remaining
}
).ToList(); //tolist may not be necessary, i just wanted to look at it
我觉得你的疑问词和你的例子不一致。你说(并在代码中做了):
If the price and type are same, based on type it need to exclude every nth item from the list and then calculate the sum. i.e type B = 3, Type C = 4
这对我来说意味着您应该按类型和价格分组,所以 B/5 是一个列表,B/10 是另一个列表。但是你接着说:
Which means in above sample data, since there are 3 items each in type B once it group by price and type it need to exclude every 3rd item when calculate sum. So sum for type B will be 5+5+10+10
我不太明白这一点。对我来说 B/5 中有 3 个项目,所以 B/5 应该是 10 的总和(B/5 + B/5 + 排除)。 B/10中有3项,同样,应该是(B/10 + B/10 + 排除),总共20项。
上面的代码没有按价格分组。它输出 2 个项目的集合,Type=B,SumWithout=30 和 Type=C,SumWithout=60。这也是按价格分组,它输出 3 项集合:
var x = items.GroupBy(g => new { g.Type, g.Price })
.Select(g => new
{
g.Key.Type,
g.Key.Price,
SumPriceWithoutNthElement =
g.Where((v, i) => (i % (dict[g.Key.Type]??2)) != ((dict[g.Key.Type] ?? 2) - 1))
.Sum(r => r.Price) }
).ToList();
项目是 Type=B,Price=5,SumWithout=10 和 Type=B,Price=10,SumWithout=20 和 Type=C,Price=15,SumWithout=60
也许你的意思是按类型和价格分组,删除每第 3 个项目(从 b 中删除第 4 个项目,等等),然后仅按类型再次分组,然后求和
这意味着如果您的 B 类价格是
1,1,1,1,2,2,2,2,2
^ ^
我们将删除一个 1 和一个 2(Ines 下面有箭头),然后总和为 9。这与删除所有类型 b 的每 3 个不同:
1,1,1,1,2,2,2,2,2
^ ^ ^
?
在这种情况下,也许可以再次按 Type/sum 对我第二个示例的 SumWithout 输出进行分组
我确实考虑过,如果没有 LINQ,可能会有更有效的方法来做到这一点。如果不是 LINQ,几乎肯定会更容易理解代码 - LINQ 不一定是一个神奇的灵丹妙药可以解决所有问题,尽管它看起来像一把可以解决所有问题的锤子,但有时最好避免
取决于您打算如何解决问题(价格是否是组键的一部分)构建字典并累积 0 而不是第 N 个元素的价格可能是一种方式.. 另一种方式,如果价格是关键的一部分,可以是对所有价格求和,然后从总价格
中减去(count/N)*价格
我有以下实体结构
public class Item
{
public EnumType Type { get; set; }
public int Price { get; set; }
}
public enum EnumType
{
A =1,
B=2,
C =3
}
我有如下物品清单
var items = new List<Item>
{
new Item{ Price=5, Type= EnumType.B},
new Item{ Price=5, Type= EnumType.B},
new Item{ Price=5, Type= EnumType.B},
new Item{ Price=10, Type= EnumType.B},
new Item{ Price=10, Type= EnumType.B},
new Item{ Price=10, Type= EnumType.B},
new Item{ Price=15, Type= EnumType.C},
new Item{ Price=15, Type= EnumType.C},
new Item{ Price=15, Type= EnumType.C},
new Item{ Price=15, Type= EnumType.C},
new Item{ Price=15, Type= EnumType.C}
};
如果价格和类型相同,则需要根据类型从列表中排除每第n项,然后计算总和。 即类型 B = 3,类型 C = 4
这意味着在上面的示例数据中,由于类型 B 中有 3 个项目,一旦按价格和类型分组,因此在计算总和时需要排除每第 3 个项目。 所以类型 B 的总和将为 5+5+10+10,类型 C 的总和将为 15+15+15+15
我试过使用模块化,但似乎方向不对
到目前为止我已经试过了
static int GetFactorByType(EnumType t)
{
switch(t)
{
case EnumType.A:
return 2;
case EnumType.B:
return 3;
case EnumType.C:
return 4;
default:
return 2;
}
}
var grp = items.GroupBy(g => new { g.Type, g.Price }).Select(s => new
{
type= s.Key.Type,
price = s.Key.Price,
count = s.Count()
}).Where(d => d.count % GetFactorByType(d.type) == 0).ToList();
按始终唯一的新对象分组可保证您拥有的组数与项目数一样多。尝试这样的事情:
var grp = items.GroupBy(g => $"{g.Type}/{g.Price}").Select(s => new
{
type= s.Value.First().Type,
price = s.Value.First().Price,
count = s.Value.Count()
}).Where(d => count % GetFactorByType(d.type) == 0).ToList();
这样,您按 type/price 组合组成的字符串进行分组,因此如果项目相等,则字符串将相等。
对于您的前三个项目示例,$"{g.Type}/{g.Price}"
字符串相当于 "B/5"
,因此它也非常可读。
这是一个解决方法:
//track the type:nth element discard
var dict = new Dictionary<EnumType, int?>();
dict[EnumType.B] = 3;
dict[EnumType.C] = 4;
//groupby turns our list of items into two collections, depending on whether their type is b or c
var x = items.GroupBy(g => new { g.Type })
.Select(g => new //now project a new collection
{
g.Key.Type, //that has the type
SumPriceWithoutNthElement = //and a sum
//the sum is calculated by reducing the list based on index position: in where(v,i), the i is the index of the item.
//We drop every Nth one, N being determined by a dictioary lookup or 2 if the lookup is null
//we only want list items where (index%N != N-1) is true
g.Where((v, i) => (i % (dict[g.Key.Type]??2)) != ((dict[g.Key.Type] ?? 2) - 1))
.Sum(r => r.Price) //sum the price for the remaining
}
).ToList(); //tolist may not be necessary, i just wanted to look at it
我觉得你的疑问词和你的例子不一致。你说(并在代码中做了):
If the price and type are same, based on type it need to exclude every nth item from the list and then calculate the sum. i.e type B = 3, Type C = 4
这对我来说意味着您应该按类型和价格分组,所以 B/5 是一个列表,B/10 是另一个列表。但是你接着说:
Which means in above sample data, since there are 3 items each in type B once it group by price and type it need to exclude every 3rd item when calculate sum. So sum for type B will be 5+5+10+10
我不太明白这一点。对我来说 B/5 中有 3 个项目,所以 B/5 应该是 10 的总和(B/5 + B/5 + 排除)。 B/10中有3项,同样,应该是(B/10 + B/10 + 排除),总共20项。
上面的代码没有按价格分组。它输出 2 个项目的集合,Type=B,SumWithout=30 和 Type=C,SumWithout=60。这也是按价格分组,它输出 3 项集合:
var x = items.GroupBy(g => new { g.Type, g.Price })
.Select(g => new
{
g.Key.Type,
g.Key.Price,
SumPriceWithoutNthElement =
g.Where((v, i) => (i % (dict[g.Key.Type]??2)) != ((dict[g.Key.Type] ?? 2) - 1))
.Sum(r => r.Price) }
).ToList();
项目是 Type=B,Price=5,SumWithout=10 和 Type=B,Price=10,SumWithout=20 和 Type=C,Price=15,SumWithout=60
也许你的意思是按类型和价格分组,删除每第 3 个项目(从 b 中删除第 4 个项目,等等),然后仅按类型再次分组,然后求和
这意味着如果您的 B 类价格是
1,1,1,1,2,2,2,2,2
^ ^
我们将删除一个 1 和一个 2(Ines 下面有箭头),然后总和为 9。这与删除所有类型 b 的每 3 个不同:
1,1,1,1,2,2,2,2,2
^ ^ ^
?
在这种情况下,也许可以再次按 Type/sum 对我第二个示例的 SumWithout 输出进行分组
我确实考虑过,如果没有 LINQ,可能会有更有效的方法来做到这一点。如果不是 LINQ,几乎肯定会更容易理解代码 - LINQ 不一定是一个神奇的灵丹妙药可以解决所有问题,尽管它看起来像一把可以解决所有问题的锤子,但有时最好避免
取决于您打算如何解决问题(价格是否是组键的一部分)构建字典并累积 0 而不是第 N 个元素的价格可能是一种方式.. 另一种方式,如果价格是关键的一部分,可以是对所有价格求和,然后从总价格
中减去(count/N)*价格