如何根据常见的 属性 过滤列表(只有这样才能找到最小值)
How to filter a list based on a common property (only then to find the min value)
问题描述:
我有一个 Manufacturers
列表的场景,每个列表包含一个 Id
、CapacityCode
、Price
。我想找到最便宜的价格,但仅限于所有制造商具有相同 CapacityCode
共同点的商品。
或
public class Manufacturer
{
public int Id { get; set; }
public string CapacityCode { get; set; }
public decimal Price { get; set; }
}
我的目标:
根据具有相同容量代码的项目过滤列表,然后找到最低价格。
例如:
{
"Manufacturers": [
{
"Id": 1,
"CapacityCode": "Foo",
"Price": 15
},
{
"Id": 1,
"CapacityCode": "Boo", // Manufacture 2 has no "Boo" so it should be filtered
"Price": 10
},
{
"Id": 2,
"CapacityCode": "Foo",
"Price": 30
},
{
"Id": 2,
"CapacityCode": "Zoo", // Manufacture 1 has no "Zoo" so it should be filtered
"Price": 20
}
}
筛选列表的输出应为:
{
{
"Id": 1,
"CapacityCode": "Foo",
"Price": 15
},
{
"Id": 2,
"CapacityCode": "Foo",
"Price": 30
}
}
所以最低价格应该是 15。
我试过了(而且有效):
var groups = source.Manufacturers
.GroupBy(m => m.CapacityCode)
.ToList();
var max = groups.Max(g => g.Count());
var filtered = new List<Manufacturer>();
foreach (var group in groups)
{
if (group.Count() != max)
continue;
filtered.AddRange(group);
}
decimal minPrice = filtered.Min(m => m.Price);
我的问题:
如何在性能和可读性方面达到相同的结果?
IIUC 你的问题,没有必要对 Manufacturer
列表进行两次分组。您可以按 CapacityCode
对其进行分组并找到最大计数。然后按最大数量过滤组并使用 SelectMany
展平项目,按 Price
排序,最后获得最低价格,如果需要的话
var groups = manufacturers
.GroupBy(m => m.CapacityCode)
.ToList();
var count = groups.Max(g => g.Count());
var result = groups
.Where(g => g.Count() == count)
.SelectMany(g => g)
.OrderBy(m => m.Price)
.ToList();
var minPrice = result.FirstOrDefault()?.Price ?? 0;
您可以按 CapacityCode
和 ToLookup
, get the max count with Max
, filter groups with the max count with Where
, flatten the groups into IEnumerable<Manufacturer>
with SelectMany
, and sort the prices with OrderBy
对制造商进行分组。
var manufacturers = new List<Manufacturer> {
new Manufacturer
{
Id = 1,
CapacityCode = "Foo",
Price = 15
},
new Manufacturer
{
Id = 1,
CapacityCode = "Boo",
Price = 10
},
new Manufacturer
{
Id = 2,
CapacityCode = "Foo",
Price = 30
}
new Manufacturer
{
Id = 2,
CapacityCode = "Zoo",
Price = 20
},
};
var groups = manufacturers.ToLookup(manufacturer => manufacturer.CapacityCode);
var maxCount = groups.Max(group => group.Count());
var result = groups
.Where(group => group.Count() == maxCount)
.SelectMany(group => group)
.OrderBy(manufacturer => manufacturer.Price)
.ToList();
问题描述:
我有一个 Manufacturers
列表的场景,每个列表包含一个 Id
、CapacityCode
、Price
。我想找到最便宜的价格,但仅限于所有制造商具有相同 CapacityCode
共同点的商品。
或
public class Manufacturer
{
public int Id { get; set; }
public string CapacityCode { get; set; }
public decimal Price { get; set; }
}
我的目标:
根据具有相同容量代码的项目过滤列表,然后找到最低价格。
例如:
{
"Manufacturers": [
{
"Id": 1,
"CapacityCode": "Foo",
"Price": 15
},
{
"Id": 1,
"CapacityCode": "Boo", // Manufacture 2 has no "Boo" so it should be filtered
"Price": 10
},
{
"Id": 2,
"CapacityCode": "Foo",
"Price": 30
},
{
"Id": 2,
"CapacityCode": "Zoo", // Manufacture 1 has no "Zoo" so it should be filtered
"Price": 20
}
}
筛选列表的输出应为:
{
{
"Id": 1,
"CapacityCode": "Foo",
"Price": 15
},
{
"Id": 2,
"CapacityCode": "Foo",
"Price": 30
}
}
所以最低价格应该是 15。
我试过了(而且有效):
var groups = source.Manufacturers
.GroupBy(m => m.CapacityCode)
.ToList();
var max = groups.Max(g => g.Count());
var filtered = new List<Manufacturer>();
foreach (var group in groups)
{
if (group.Count() != max)
continue;
filtered.AddRange(group);
}
decimal minPrice = filtered.Min(m => m.Price);
我的问题:
如何在性能和可读性方面达到相同的结果?
IIUC 你的问题,没有必要对 Manufacturer
列表进行两次分组。您可以按 CapacityCode
对其进行分组并找到最大计数。然后按最大数量过滤组并使用 SelectMany
展平项目,按 Price
排序,最后获得最低价格,如果需要的话
var groups = manufacturers
.GroupBy(m => m.CapacityCode)
.ToList();
var count = groups.Max(g => g.Count());
var result = groups
.Where(g => g.Count() == count)
.SelectMany(g => g)
.OrderBy(m => m.Price)
.ToList();
var minPrice = result.FirstOrDefault()?.Price ?? 0;
您可以按 CapacityCode
和 ToLookup
, get the max count with Max
, filter groups with the max count with Where
, flatten the groups into IEnumerable<Manufacturer>
with SelectMany
, and sort the prices with OrderBy
对制造商进行分组。
var manufacturers = new List<Manufacturer> {
new Manufacturer
{
Id = 1,
CapacityCode = "Foo",
Price = 15
},
new Manufacturer
{
Id = 1,
CapacityCode = "Boo",
Price = 10
},
new Manufacturer
{
Id = 2,
CapacityCode = "Foo",
Price = 30
}
new Manufacturer
{
Id = 2,
CapacityCode = "Zoo",
Price = 20
},
};
var groups = manufacturers.ToLookup(manufacturer => manufacturer.CapacityCode);
var maxCount = groups.Max(group => group.Count());
var result = groups
.Where(group => group.Count() == maxCount)
.SelectMany(group => group)
.OrderBy(manufacturer => manufacturer.Price)
.ToList();