如何基于数字列表和/或规则找到复杂的排列,c# /Linq

本文关键字:复杂 排列 Linq 规则 数字 何基于 列表 | 更新日期: 2023-09-27 18:05:08

当前的问题是代码可以工作,但是随着传入的组合越来越多,它变得指数级慢。(输入15个组合后,计算时间大于5秒。)我需要能够传递多达100个组合,仍然得到一个结果回来,需要不到2秒。

我打赌Linq查询可以解决这个问题?

我想要达到的目标:

{1, 2, 3} + {1, 5, 26, 40} = 12 combinations:
[1,1]
[1,5]
[1,26]
[1,40]
[2,1]
[2,5]
[2,26]
[2,40]
[3,1]
[3,5]
[3,26]
[3,40]

然而,上面的例子只包含2个组合集。我应该可以传入任意数量的组合集


最接近的东西,看起来像它是类似于我想要的最终结果,由于是快速和高效的,是一个linq查询,处理大部分或所有的逻辑在它。示例:从数字列表中获取所有可能的组合

public IEnumerable<IEnumerable<T>> GetPowerSet<T>(List<T> list)
{
    return from m in Enumerable.Range(0, 1 << list.Count)
              select
                  from i in Enumerable.Range(0, list.Count)
                  where (m & (1 << i)) != 0
                  select list[i];
}

工作代码示例:


[Test]
public void StackOverflowExample_Simple()
{
    var list1 = new List<int>() { 1, 2, 3 };
    var list2 = new List<int>() { 1, 5, 26, 40 };
    var myListsOfNumberCombinations = new List<List<int>>() { list1, list2 };
    var results = GetAllPossibleCombinations(myListsOfNumberCombinations);
    Assert.AreEqual(12, results.Count());
    StringBuilder sb = new StringBuilder();
    foreach (var result in results)
    {
        foreach (var number in result.OrderBy(x => x))
        {
            sb.Append(number + ",");
        }
        sb.Append("|");
    }
    string finalResult = sb.ToString().Replace(",|", "|");
    Assert.AreEqual(finalResult, "1,1|1,5|1,26|1,40|1,2|2,5|2,26|2,40|1,3|3,5|3,26|3,40|");
}
[Test]
public void StackOverflowExample_TakesALongTime()
{
    var list1 = new List<int>() { 1, 2, 3 };
    var list2 = new List<int>() { 4, 5 };
    var list3 = new List<int>() { 1, 6 };
    var list4 = new List<int>() { 2, 5 };
    var list5 = new List<int>() { 1, 3, 55, 56 };
    var list6 = new List<int>() { 3, 4, 7, 8, 9 };
    var myListsOfNumberCombinations = new List<List<int>>() { list1, list2, list3, list4, list5, list1, list1, list1, list3, list4, list4, list5, list6, list6, list2 };

    DateTime startTime = DateTime.Now;
    var results = GetAllPossibleCombinations(myListsOfNumberCombinations);
    Assert.AreEqual(4147200, results.Count());
    var duration = DateTime.Now.Subtract(startTime).TotalSeconds;

    //duration = about 4 or 5 seconds
    Assert.Less(duration, 10); //easy place to put a breakpoint
}

public IEnumerable<IEnumerable<int>> GetAllPossibleCombinations(List<List<int>> combinationSets)
{
    List<List<int>> returnList = new List<List<int>>();
    _RecursiveGetMoreCombinations(
        ref returnList,
        new List<int>(),
        combinationSets,
        0);
    return returnList;
}
private void _RecursiveGetMoreCombinations(
    ref List<List<int>> returnList,
    List<int> appendedList,
    List<List<int>> combinationSets,
    int index)
{
    var combinationSet = combinationSets[index];
    foreach (var number in combinationSet)
    {
        List<int> newList = appendedList.AsEnumerable().ToList();
        newList.Add(number);
        if (combinationSets.Count() == index + 1)
        {
            returnList.Add(newList);
        }
        else
        {
            _RecursiveGetMoreCombinations(
                ref returnList,
                newList,
                combinationSets,
                index + 1);
        }
    }    
}

如何基于数字列表和/或规则找到复杂的排列,c# /Linq

你能不能把第一组和第三组(或组)进行排列,然后把'45'(与组)或其他静态数字放在这些数字之间?

如果4和5(在本例中)总是出现,则不需要在排列逻辑中包含它们。