Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 查找与所有其他项目相关的项目_C#_Linq - Fatal编程技术网

C# 查找与所有其他项目相关的项目

C# 查找与所有其他项目相关的项目,c#,linq,C#,Linq,我有以下课程: public class Relation { public Int32 SourceId { get; set; } public Int32 TargetId { get; set; } } 以及下列名单: List<Relation> relations = service.GetRelations(); 在这种情况下,TargetId可以是1或2 与所有targetID(1,2)相关的唯一SourceId是sourceID1 SourceId 2仅

我有以下课程:

public class Relation {
  public Int32 SourceId { get; set; }
  public Int32 TargetId { get; set; }
}
以及下列名单:

List<Relation> relations = service.GetRelations();
在这种情况下,
TargetId
可以是1或2

与所有
targetID(1,2)
相关的唯一
SourceId
sourceID1

SourceId 2
仅与
TargetId 1
相关,
SourceId 3
仅与
TargetId 2
相关


我如何才能做到这一点?

以下代码满足您的要求。它有一种单元测试的形式,因此您可以检查不同的场景

        [Fact]
        public void FindSourcesThatTargetAll()
        {
            var list = new List<Relation>
            {
                new Relation(1, 1), new Relation(1, 2), new Relation(2, 1), new Relation(3, 2)

            };
            var allTargets = list.Select(x => x.TargetId).Distinct().OrderBy(x=>x).ToList();

            var dict = list.GroupBy(x => x.SourceId).ToDictionary(x => x.Key,
                grouping => grouping.Select(y => y.TargetId).Distinct().OrderBy(x=>x).ToList());

            var sourcesThatTargetAll = dict.Where(x => x.Value.Count == allTargets.Count).Select(x => x.Key).ToList();

            Assert.Single(sourcesThatTargetAll);
            Assert.Equal(1, sourcesThatTargetAll.First());

        }
[事实]
public void FindSourcesThatTargetAll()
{
变量列表=新列表
{
新关系(1,1),新关系(1,2),新关系(2,1),新关系(3,2)
};
var allTargets=list.Select(x=>x.TargetId).Distinct().OrderBy(x=>x.ToList();
var dict=list.GroupBy(x=>x.SourceId).ToDictionary(x=>x.Key,
grouping=>grouping.Select(y=>y.TargetId).Distinct().OrderBy(x=>x.ToList());
var sourcesThatTargetAll=dict.Where(x=>x.Value.Count==allTargets.Count);
Assert.Single(sourcesThatTargetAll);
等于(1,sourcesThatTargetAll.First());
}
基本上,我做到了:

  • 找到所有的目标
  • 对于每个源,找到所有目标(不同的目标很重要),并根据字典中的源对其进行分组(
    dict
    variable)
  • 从上面的字典中选择与所有目标匹配的所有源(示例中的计数足够了,但您可以进行更复杂的比较)

  • 您需要收集所有可能的目标ID:

    var input = new []
    {
        new Relation(1, 1),
        new Relation(1, 2),
        new Relation(2, 1), 
        new Relation(3, 2), 
    };
    
    var allTargetId = input.Select(x => x.TargetId).Distinct().ToArray();
    
    然后按源id分组,并在每组中检查
    allTargetId
    中显示的所有组成员:

    (1, 1), (1, 2), (2, 1), (3, 2)
    
    var result = input.GroupBy(x => x.SourceId, x => x.TargetId)
        .Where(g => allTargetId.All(x => g.Contains(x)))
        .Select(g => g.Key)
        .ToArray();
    
    注意:为了使这段代码正常工作,我在
    关系
    类中添加了一个构造函数

    public class Relation
    {
        public Relation(int sourceId, int targetId)
        {
            SourceId = sourceId;
            TargetId = targetId;
        }
    
        public Int32 SourceId { get; set; }
        public Int32 TargetId { get; set; }
    }
    

    编辑

    要获取
    关系
    ,可以使用以下查询:

    var result = input.GroupBy(x => x.SourceId)
        .Where(g => allTargetId.All(x => g.Select(y => y.TargetId).Contains(x)))
        .SelectMany(g => g)
        .ToArray();
    

    请注意,我只使用LINQ2对象对其进行了测试,因此我不确定如何将其转换为SQL

    实现这一点的简单方法是按
    TargetId
    对记录进行分组,然后找到所有
    SourceId
    的交集

    var groups = relations.GroupBy(r => r.TargetId).ToArray();
    if (groups.Length > 0) {
        var set = new HashSet<int>(groups[0]);
        for (int i = 1; i < groups.Length; ++i)
            set.IntersectWith(groups[i].Select(r => r.SourceId));
    }
    
    var groups=relations.GroupBy(r=>r.TargetId.ToArray();
    如果(groups.Length>0){
    var set=新的HashSet(组[0]);
    对于(int i=1;ir.SourceId));
    }
    
    在此
    集合的末尾
    将包含与所有
    TargetId
    s

    公共类关系相关的所有
    SourceId
    s
        public class Relation
        {
            public Int32 SourceId { get; set; }
            public Int32 TargetId { get; set; }
        }
    
        public Int32?[] FindRelation(Relation[] relations)
        {
            List<Int32?> sourceIds = new List<int?>;
            var countOfTargets = relations.Select(x => x.TargetId).Distinct().Count();
    
            var relationsGroupedBySource = relations.GroupBy(x => x.SourceId);
    
            foreach (var group in relationsGroupedBySource)
            {
                var distinctGroup = group.Distinct();
    
                if (distinctGroup.Count() == countOfTargets)
                {
                    sourceIds.Add(distinctGroup.Select(x => x.SourceId).First());
                }
            }
    
            return sourceIds.ToArray();
        }
    
      public void Test()
      {
            Relation[] relations = { 
                                       new Relation() { SourceId = 1, TargetId = 1 },
                                       new Relation() { SourceId = 1, TargetId = 2 },
                                       new Relation() { SourceId = 2, TargetId = 1 },
                                       new Relation() { SourceId = 3, TargetId = 2 }
                                   };
    
         var sourceIds = FindRelation(relations);
      }
    
    { 公共Int32源ID{get;set;} public Int32 TargetId{get;set;} } 公共Int32?[]查找关系(关系[]关系) { List sourceid=新列表; var countOfTargets=relations.Select(x=>x.TargetId).Distinct().Count(); var relationsGroupedBySource=relations.GroupBy(x=>x.SourceId); foreach(关系GroupedBySource中的var组) { var distinctGroup=group.Distinct(); if(distinctGroup.Count()=目标计数) { Add(distinctGroup.Select(x=>x.SourceId.First()); } } 返回sourceIds.ToArray(); } 公开无效测试() { 关系[]关系={ 新关系(){SourceId=1,TargetId=1}, 新关系(){SourceId=1,TargetId=2}, 新关系(){SourceId=2,TargetId=1}, 新关系(){SourceId=3,TargetId=2} }; var sourceIds=FindRelation(关系); }
    ?但如何使用GroupBy获取与所有TargetID相关的SourceID?使用GroupBy是我的第一个想法,但现在确定如何。。。也许我遗漏了什么。你说你需要一个LINQ答案,因为EF的使用,但是
    关系
    不是
    IQueryable
    ,它是一个
    列表
    ,所以不涉及EF。我只需要使用Linq作为实体的查询framework@MiguelMoura然后,您应该更新问题和标记以反映这一点。是否可以在最后获得关系而不是SourceId?@MiguelMoura有to
    关系
    匹配-
    (1,1)、(1,2)
    。你想要哪一个?全部?如果可能的话,我希望两者都得到,因为SourceId=1与所有TargetId相关。我知道这些对(SourceId,TargetId)是唯一的。知道这一点是必要的,part.GroupBy(x=>x.SourceId,x=>x.TargetId)?@MiguelMoura我已经更新了我的答案。“编辑”部分中的代码应返回满足条件的所有关系。我只需要使用Linq,而不需要使用循环,因为我使用的是实体框架。对代码的解释将有助于OP和其他人更好地理解您的答案。仅仅发布你的代码会让其他人感到困惑。