C# 将列表与列表匹配

C# 将列表与列表匹配,c#,C#,所以我有一张发票和交易清单。我需要根据这两个付款进行发票匹配。比方说 List<int> invoices = new List<int> { 40, 30, 10, 20, 60, 4, 6 }; List<int> payments = new List<int> { 80, 90 }; List invoices=新列表{40,30,10,20,60,4,6}; 名单付款=新名单{80,90}

所以我有一张发票和交易清单。我需要根据这两个付款进行发票匹配。比方说

            List<int> invoices = new List<int> { 40, 30, 10, 20, 60, 4, 6 };
            List<int> payments = new List<int> { 80, 90 };
List invoices=新列表{40,30,10,20,60,4,6};
名单付款=新名单{80,90};
我想找到与第一笔付款(80)完全匹配的可能组合,然后根据剩下的发票,我希望它与第二笔付款(90)匹配

因此,发票列表中的第一部分40、30和10应与付款列表(80)中的第一项匹配,20、60、4和6应与付款列表(90)中的第二项匹配


我只能用递归的方法匹配1笔付款。

您所需要的只是一个神奇的方法。它遍历所有可能的变量,并返回第一个合适的索引组合或null。它还需要一组索引,这些索引将从搜索中排除;您可以很容易地将上次搜索的结果提供给它


静态int[]匹配(列出发票、int付款、int[]排除=默认)
{
如果(exclude==default)exclude=newint[0];
所选列表=新列表();
sbyte加法(整数)
{
int结果=所选。总和(索引=>发票[索引])+编号;
如果(结果<付款)返回-1;
如果(结果>付款)返回1;
返回0;
}
bool Continue(int start)
{
对于(变量i=开始;i付款)继续;
如果(发票[i]==付款)返回新的整数[]{i};
选定。添加(i);
if(Continue(i+1))返回selected.ToArray();
选定。删除(i);
}
返回null;
}

正在运行的代码


小心。 因为有这么多的组合,所以需要一些时间来处理它们(尤其是大型阵列)。
如果你有多种方法来组合第一次付款,但只有一个或几个组合留下的数字可以组合在第二次付款中?听起来好像你想要某种形式的改变,我想只考虑完美的组合。由于将有多个组合,因此将选择两个匹配的唯一完美组合。但在您的示例中有几个“完美”组合:{60,20}{40,30,10,4,6}{40,10,20,4,6}{30,60}等等。它应该返回第一个有效的组合吗?不清楚您定义的“完美”是什么。
static int[] Match(List<int> invoices, int payment, int[] exclude = default)
        {
            if (exclude == default) exclude = new int[0];
            List<int> selected = new List<int>();
            sbyte Add(int number)
            {
                int result = selected.Sum(index => invoices[index]) + number;
                if (result < payment) return -1;
                if (result > payment) return 1;
                return 0;
            }
            bool Continue(int start)
            {
                for (var i = start; i < invoices.Count; i++)
                {
                    if (exclude.Contains(i)) continue;
                    switch (Add(invoices[i]))
                    {
                        case 1:
                            break;
                        case -1:
                            selected.Add(i);
                            if (Continue(i + 1))
                                return true;
                            selected.Remove(i);
                            break;
                        case 0:
                            selected.Add(i);
                            return true;
                    }
                }
                return false;
            }
            for (int i = 0; i < invoices.Count; i++)
            {
                if (exclude.Contains(i) || invoices[i] > payment) continue;
                if (invoices[i] == payment) return new int[] { i };
                selected.Add(i);
                if (Continue(i + 1)) return selected.ToArray();
                selected.Remove(i);
            }
            return null;
        }