C# 如何过滤带条件的整型列表?

C# 如何过滤带条件的整型列表?,c#,C#,我有这个列表: 此列表中有6个列表,包含从1到4的数字,每个数字的出现次数为3 我想对其进行过滤,以获得: {{1,2}{1,3}{2,4}{3,4}} 这里每个数字的出现次数为2 列表是动态生成的,我希望能够根据事件进行动态筛选 编辑更多详细信息 我需要计算一个数字在列表中包含多少次,因为上面的例子是3。然后我想从列表中排除列表,以便将次数从3次减少到2次, 对我来说,主要的问题是找到一种不阻塞我的计算机的方法:),并且让每个数字出现2次(强制) 如果总是两个数字的组合,并且它们必须在列表中

我有这个
列表

此列表中有6个列表,包含从1到4的数字,每个数字的出现次数为3

我想对其进行过滤,以获得:

{{1,2}{1,3}{2,4}{3,4}}
这里每个数字的出现次数为2

列表是动态生成的,我希望能够根据事件进行动态筛选

编辑更多详细信息

我需要计算一个数字在
列表中包含多少次,因为上面的例子是3。然后我想从
列表中排除列表
,以便将次数从3次减少到2次,
对我来说,主要的问题是找到一种不阻塞我的计算机的方法:),并且让每个数字出现2次(强制)

如果总是两个数字的组合,并且它们必须在列表中出现N次,这意味着取决于N个数字:

4(不同数字)x2(它们必须出现的次数)=8个数字=4对

4 x 3(次)=12=6(对)

4 x 4=16=8对

这意味着,我们必须从6对中选择4对最符合标准的

所以基于基本的组合学() 我们有一个6/2! = (6*5*4*3*2*1)/(2*1)=360种可能的排列

基本上,你可以有360种不同的方式把第二个列表放在一起

因为列表中项目的排列方式(列表中项目的顺序)无关紧要,所以可能的组合数是6/(2!*4!) = 15

所以问题是——你有15个可能的答案来回答你的问题。 这意味着-你只需要在上面循环15次。 只有15种方法可以从6项列表中选择4项

这似乎是你“杀死机器”问题的解决方案

那么下一个问题——我们如何找到所有可能的“组合” 让我们定义可以从输入数组中选取的所有可能项 例如第一、第二、第三和第四

1,2,3,4。。。。。。。1,2,3,5...... 1,2,3,6

所有的组合都是(从这里开始)

静态IEnumerable GetKCombs(IEnumerable列表,int-length),其中T:IComparable
{
if(length==1)返回列表。选择(t=>newt[]{t});
返回GetKCombs(列表,长度-1)
.SelectMany(t=>list.Where(o=>o.CompareTo(t.Last())>0),
(t1,t2)=>t1.Concat(新的T[]{t2});
}
并使用调用(因为有6个项目可供选择,索引对象为0、1、2、3、4和5)

var-possiblePicks=GetKCombs(新列表{0,1,2,3,4,5},4);
我们有15种可能的组合 现在,我们试着从第一个列表中选取4个元素,并检查它们是否符合标准。。如果不是。。然后用另一个组合

 var data = new List<List<int>>
            {
                new List<int> { 1,2 },
                new List<int> { 1,3 },
                new List<int> { 1,4 },
                new List<int> { 2,3 },
                new List<int> { 2,4 },
                new List<int> { 3,4 }
            };


  foreach (var picks in possiblePicks)
            {
                var listToTest = new List<List<int>>(4);
                foreach (var i in picks)
                    listToTest.Add(data[i]);

                var ok = Check(listToTest, 2);
                if (ok)
                    break;
            }



  private bool Check(List<List<int>> listToTest, int limit)
        {
            Dictionary<int, int> ret = new Dictionary<int, int>();
            foreach (var inputElem in listToTest)
            {
                foreach (var z in inputElem)
                {
                    var returnCount = ret.ContainsKey(z) ? ret[z] : 0;
                    if (!ret.ContainsKey(z))
                        ret.Add(z, returnCount + 1);
                    else
                        ret[z]++;
                }

            }
            return ret.All(p => p.Value == limit);
        }
var数据=新列表
{
新列表{1,2},
新名单{1,3},
新名单{1,4},
新名单{2,3},
新名单{2,4},
新名单{3,4}
};
foreach(可能的风险值选择)
{
var listToTest=新列表(4);
foreach(拾取中的var i)
列表测试添加(数据[i]);
var ok=检查(列表测试,2);
如果(确定)
打破
}
私有布尔检查(列表列表ToTest,整数限制)
{
字典ret=新字典();
foreach(listToTest中的var inputElem)
{
foreach(输入项中的变量z)
{
var returnCount=ret.ContainsKey(z)?ret[z]:0;
如果(!ret.ContainsKey(z))
ret.Add(z,returnCount+1);
其他的
ret[z]++;
}
}
返回ret.All(p=>p.Value==limit);
}
我相信这可以进一步优化,以最小化除“listToTest”之外的迭代量


此外,这是一个惰性实现(Ienumerable)——因此,如果第一次(或第二次)组合成功,它将停止迭代。

我接受了Marty的答案,因为修复了我的问题,尝试使用他的方法处理更大的列表,我发现我的自阻塞再次出现在我的计算机上,因此我开始寻找另一种方法,并最终使用以下方法:

var main = new List<HashSet<int>> {
            new HashSet<int> {1,2},
            new HashSet<int> {1,3},
            new HashSet<int> {1,4},
            new HashSet<int> {2,3},
            new HashSet<int> {2,4},
            new HashSet<int> {3,4} };


        var items = new HashSet<int>(from l in main from p in l select p); //=>{1,2,3,4}


        for (int i =main.Count-1;i-->0; )
        {               
            var occurence=items.Select(a=> main.Where(x => x.Contains(a)).Count()).ToList();
            var occurenceSum = 0;
            foreach(var j in main[i])
            {
                occurenceSum += occurence[j - 1];
                if (occurenceSum==6) //if both items have occurence=3, then the sum=6, then I can remove that list!
                {
                    main.RemoveAt(i);

                }
            }             

        }
var main=新列表{
新哈希集{1,2},
新哈希集{1,3},
新哈希集{1,4},
新哈希集{2,3},
新哈希集{2,4},
新哈希集{3,4};
var items=新哈希集(从主列表中的l开始,从l中的p开始,选择p);//=>{1,2,3,4}
对于(int i=main.Count-1;i-->0;)
{               
var occurrence=items.Select(a=>main.Where(x=>x.Contains(a)).Count()).ToList();
var-occurrencesum=0;
foreach(主[i]中的var j)
{
发生次数总和+=发生次数[j-1];
if(occurrencesum==6)//如果两个项目的occurrence=3,那么sum=6,那么我可以删除该列表!
{
主移除(i);
}
}             
}

您可以添加更多有关要添加哪些元组的详细信息吗?(对我来说)你想达到什么目的还不太清楚。听起来像是直接从:-)我喜欢@ReneéVogt他想删除这些元组,删除这些元组会导致所有单个数字出现一定次数,例如。2@GediminasMasaitis到目前为止,我理解这一点。我只是想知道Will Harrison的伪代码是否是正确的方法,或者对于结果集,是否有元组比其他元组更可取。@GediminasMasaitis在Will Harrison的答案中,{2,3}将被添加到结果中,并因此跳过最后的元组。如果OP真的想要他展示的结果,我认为这个问题离题了,或者
 var possiblePicks = GetKCombs(new List<int> { 0, 1, 2, 3, 4, 5 }, 4);
 var data = new List<List<int>>
            {
                new List<int> { 1,2 },
                new List<int> { 1,3 },
                new List<int> { 1,4 },
                new List<int> { 2,3 },
                new List<int> { 2,4 },
                new List<int> { 3,4 }
            };


  foreach (var picks in possiblePicks)
            {
                var listToTest = new List<List<int>>(4);
                foreach (var i in picks)
                    listToTest.Add(data[i]);

                var ok = Check(listToTest, 2);
                if (ok)
                    break;
            }



  private bool Check(List<List<int>> listToTest, int limit)
        {
            Dictionary<int, int> ret = new Dictionary<int, int>();
            foreach (var inputElem in listToTest)
            {
                foreach (var z in inputElem)
                {
                    var returnCount = ret.ContainsKey(z) ? ret[z] : 0;
                    if (!ret.ContainsKey(z))
                        ret.Add(z, returnCount + 1);
                    else
                        ret[z]++;
                }

            }
            return ret.All(p => p.Value == limit);
        }
var main = new List<HashSet<int>> {
            new HashSet<int> {1,2},
            new HashSet<int> {1,3},
            new HashSet<int> {1,4},
            new HashSet<int> {2,3},
            new HashSet<int> {2,4},
            new HashSet<int> {3,4} };


        var items = new HashSet<int>(from l in main from p in l select p); //=>{1,2,3,4}


        for (int i =main.Count-1;i-->0; )
        {               
            var occurence=items.Select(a=> main.Where(x => x.Contains(a)).Count()).ToList();
            var occurenceSum = 0;
            foreach(var j in main[i])
            {
                occurenceSum += occurence[j - 1];
                if (occurenceSum==6) //if both items have occurence=3, then the sum=6, then I can remove that list!
                {
                    main.RemoveAt(i);

                }
            }             

        }