获取按名称分组的列表的所有组合
本文关键字:列表 组合 获取 | 更新日期: 2023-09-27 18:30:52
我有以下TestParam列表...这只是一个参数列表,用于确定查询的运行方式。在以下情况下,预期结果将针对不同参数的所有组合执行。因此,一个列表列表,其中 CustomerId 33 以及列表中的每个产品 ID ...
List<TestParam> testList = new List<TestParam>();
testList.Add(new TestParam() { Name = "CustomerId", Value = "33" });
testList.Add(new TestParam() { Name = "ProductId", Value = "1" });
testList.Add(new TestParam() { Name = "ProductId", Value = "2" });
testList.Add(new TestParam() { Name = "ProductId", Value = "3" });
testList.Add(new TestParam() { Name = "ProductId", Value = "4" });
testList.Add(new TestParam() { Name = "ProductId", Value = "5" });
testList.Add(new TestParam() { Name = "ProductId", Value = "6" });
testList.Add(new TestParam() { Name = "ProductId", Value = "7" });
testList.Add(new TestParam() { Name = "ProductId", Value = "8" });
TestParam 是一个普通封装的参数类,具有名称和值...
public class TestParam
{
public string Name { get; set; }
public string Value { get; set; }
}
最终结果将是一个列表列表,具有 CustomerId 33,以及所有其他产品。如果我在 TestParam 列表中有不同的名称和值,将获得相同的结果(以上只是一个示例)。
下面的代码,最终有几个列表,具体取决于上面列表的组合......
// First get a list of distinct unique param collections...
List<string> distinctParameterNames = new List<string>();
testList.GroupBy(x => x.Name).ForEach(paramName => {
distinctParameterNames.Add(paramName.Key);
});
// Get counts
List<int> combinationList = new List<int>();
foreach (var x in distinctParameterNames) {
combinationList.Add(testList.Where(y=>y.Name == x).Count());
}
// Will contain 2 lists, one having all combinations of parameters named CustomerId, and another with ProductId combinations...
List<List<TestParam>> parameterList = new List<List<TestParam>>();
foreach (var x in distinctParameterNames) {
// Loop
List<TestParam> parameter = new List<TestParam>();
testList.Where(paramName => paramName.Name == x).ForEach(y =>
{
parameter.Add(new TestParam() { Name = y.Name, Value = y.Value });
});
parameterList.Add(parameter);
}
这将是列表之间的交叉点,最终结果将是一个列表列表,每个列表将具有以下组合......所以运行将返回(在这种情况下):
- 客户 33,产品 ID 1
- 客户 33,产品 ID 2
- 客户 33,产品 ID 3
- 客户 33,产品 ID 4
- 客户 33,产品 ID 5
- 客户 33,产品 ID 6
- 客户 33,产品 ID 7
- 客户 33,产品 ID 8
最有效和最通用的方法是什么?
以下是我一直在寻找的解决方案...
public static List<List<T>> AllCombinationsOf<T>(params List<T>[] sets)
{
// need array bounds checking etc for production
var combinations = new List<List<T>>();
// prime the data
foreach (var value in sets[0])
combinations.Add(new List<T> { value });
foreach (var set in sets.Skip(1))
combinations = AddExtraSet(combinations, set);
return combinations;
}
private static List<List<T>> AddExtraSet<T>
(List<List<T>> combinations, List<T> set)
{
var newCombinations = from value in set
from combination in combinations
select new List<T>(combination) { value };
return newCombinations.ToList();
}
用法(继续我的问题本身的代码片段):
var intersection = AllCombinationsOf(parameterList.ToArray());
像
这样首先获取所有客户列表
var customers = from a in testlist where a.name='customerid'
select a;
var products = from a in testlist where a.name='productid'
select a;
然后循环客户
for(var c in customers)
{
loop products
for(var p in products)
{
var customerproducts = new CustomerProducts{
Customer = c.Name +' ' + c.Value
Product = p.Name + ' ' + p.value
};
then add it into a list
}
}
列表需要按Name
分组,然后可以根据组数多次连接:
var groups = testList.GroupBy(_ => _.Name);
IEnumerable<IEnumerable<TestParam>> result = null;
foreach (var g in groups)
{
var current = g.Select(_ => new[] { _ });
if (result == null)
{
result = current;
continue;
}
result = result.Join(current, _ => true, _ => true, (actual, c) => actual.Concat(c));
}
// check result
foreach (var i in result)
{
Console.WriteLine(string.Join(", ", i.Select(_ => string.Format("{0}-{1}", _.Name, _.Value))));
}