我具有以下实体结构
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();
答案 0 :(得分:1)
这是一个解决方法:
//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
在我看来,您的疑问词和您的示例不符。您说过(并在代码中做了):
如果价格和类型相同,则基于类型,需要从列表中排除第n个项目,然后计算总和。即类型B = 3,类型C = 4
对我来说,这意味着您应该按类型和价格分组,因此B / 5是一个列表,而B / 10是另一个列表。但是你然后说:
在上述示例数据中,这意味着B型中一旦有3个商品按价格分组并按价格分组,则在计算总和时需要排除每3个商品。所以类型B的总和是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中删除,从c中删除第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
^ ^ ^
?
在这种情况下,也许再按类型/总和分组第二个示例中的SumWithout输出
我确实认为,如果没有LINQ,可能会有更有效的方法来执行此操作。如果非LINQ,几乎可以肯定会更容易理解代码-LINQ不一定是可以杀死的绝妙魔术所有的问题,即使看起来像锤子,也可以解决所有问题,有时还是要避免
取决于您打算解决问题的方式(是否价格是组密钥的一部分),构建字典并每N个元素累积0而不是价格,这可能是一种方法。另一种方法,如果price是成为关键的一部分,可以是对所有价格求和,然后从总价格中减去(count / N)* price
答案 1 :(得分:0)
通过始终是唯一的新对象进行分组,可以确保您拥有与项目一样多的组。尝试这样的事情:
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();
这样,您将由类型/价格组合组成的字符串分组,因此,如果项目相等,则字符串将相等。
在您的前三个示例中,$"{g.Type}/{g.Price}"
字符串等于"B/5"
,因此也很容易理解。