【问题标题】:LINQ Intersect based on Property基于属性的 LINQ 相交
【发布时间】:2018-11-19 21:01:48
【问题描述】:

我试图在两个集合上找到一个交集,其中项目重叠并具有相反的状态。

public class Sample
{
    public int SampleNumber { get; set; }
    public DateTime StartTime { get; set; }
    public DateTime EndTime { get; set; }
    public bool SampleState { get; set; }
}

例子:

List<Sample> ListOfSamples1 = new List<Sample>();
List<Sample> ListOfSamples2 = new List<Sample>();

ListOfSamples1.Add( new Sample() {SampleNumber=1, StartTime = new DateTime(2018, 12, 1, 0, 0, 0), EndTime = new DateTime(2018, 12, 1, 0, 10, 0), SampleState= true });
ListOfSamples1.Add( new Sample() {SampleNumber=2, StartTime = new DateTime(2018, 12, 1, 0, 20, 0), EndTime = new DateTime(2018, 12, 1, 0, 30, 0), SampleState= false });

ListOfSamples2.Add( new Sample() {SampleNumber=3, StartTime = new DateTime(2018, 12, 1, 0, 5, 0), EndTime = new DateTime(2018, 12, 1, 0, 7, 0), SampleState= false});
ListOfSamples2.Add( new Sample() {SampleNumber=4, StartTime = new DateTime(2018, 12, 1, 0, 21, 0), EndTime = new DateTime(2018, 12, 1, 0, 22, 0), SampleState= true});

我想从ListOfSamples2 返回与ListOfSamples1 中存在的样本相交的样本,而SampleState 是相反的。

例如ListOfSamples2[0] 有一个StartTimeEndTime,它们确实驻留在ListOfSamples1[0] 中,它们的状态是相反的。

我正在使用ForEach 执行此操作,但我正在寻找一种更优雅的方式来执行此操作,它有更多选择。

谢谢

【问题讨论】:

  • 我正在尝试了解 Linq 相交,在阅读后似乎如果我想使用 Intersect 我需要一个比较器。我对 Linq 并不了解,否则我不会在这里。我尝试了一个 IEqualityComparer public class SampleComparer2 : IEqualityComparer { public bool Equals(Sample xrSample, Sample islSample) { return xrSample.StateType != islSample.StateType; } public int GetHashCode(Sample sample) { return sample.GetHashCode(); } }
  • 交集 是集合论中的一个术语。在关系代数中,这同样被称为 join
  • A set Intersect 与 time period intersect 不同,我认为这在这里令人困惑,因为 LINQ 有一个 Intersect 方法。也许如果你说重叠会更清楚?另外,那么您可以澄清重叠是否足够,或者您需要一个时间段的遏制?它可以在任何一个方向发生吗?
  • 感谢您的澄清和帮助。是的,我会说重叠就足够了。

标签: c# linq join intersect


【解决方案1】:

如果我正确理解了这个问题,那么您正在尝试做的事情相当于

public static IEnumerable<Sample> MakeSamples(
    IEnumerable<Sample> listOfSamples1,
    IEnumerable<Sample> listOfSamples2) =>
    listOfSamples2.Where(s2 =>
        listOfSamples1.Any(s1 =>
            s1.SampleState != s2.SampleState &&
            s2.EndTime >= s1.StartTime &&
            s2.StartTime <= s1.EndTime));

【讨论】:

    【解决方案2】:

    正如你提到的,你试图理解linq

    在这里我创建了一个linq 查询来做你想做的事。

        List<Sample> intersectSample =
        (from sample in ListOfSamples2
            where
                ListOfSamples1.Any(s => s.StartTime < sample.StartTime &&
                                        s.EndTime > sample.EndTime &&
                                        s.SampleState != sample.SampleState)
            select sample).ToList();
    

    它将搜索List2中的每个条目(与foreach(Sample sample in ListOfSamles2)相同),如果在List1中找到任何满足所有条件的条目(与嵌套foreach循环相同),它将选择该条目( sample) ofList2` 并将其存储在结果列表中。

    同样的事情也可以像下面那样做。

    List<Sample> intersectSampleLamadaOnly = ListOfSamples2.Where(sample =>
           ListOfSamples1.Any(s => 
                 s.StartTime < sample.StartTime && 
                 s.EndTime > sample.EndTime && 
                 s.SampleState != sample.SampleState)).ToList();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-07
      相关资源
      最近更新 更多