-3

I have one list like as

[15/05/2019 10:01]
[15/05/2019 10:03]
[15/05/2019 10:05]
[15/05/2019 10:09]
[15/05/2019 10:11]
[15/05/2019 10:19]
[15/05/2019 10:22]
[15/05/2019 10:28]
[15/05/2019 10:30]
[15/05/2019 10:35]
[15/05/2019 10:38]
[15/05/2019 10:42]
[15/05/2019 10:45]
[15/05/2019 10:55]
[15/05/2019 11:01]
[15/05/2019 11:11]
[15/05/2019 11:18]
[15/05/2019 11:25]
[15/05/2019 11:29]
[15/05/2019 11:41]

I have another list

[StartTime=15/05/2019 10:08,EndTime=15/05/2019 10:28]
[StartTime=15/05/2019 10:42,EndTime=15/05/2019 10:48]
[StartTime=15/05/2019 11:20,EndTime=15/05/2019 11:26]

result

[StartTime=15/05/2019 10:01,EndTime=15/05/2019 10:05]
[StartTime=15/05/2019 10:30,EndTime=15/05/2019 10:38]
[StartTime=15/05/2019 10:55,EndTime=15/05/2019 11:18]
[StartTime=15/05/2019 11:29,EndTime=15/05/2019 11:41]

if it's possible to get the start and end time using LINQ or for loop

For ex: 1) select 1st item in second list

[StartTime=15/05/2019 10:08,EndTime=15/05/2019 10:28]

and check below timings in the first list that needs to be a result like

[15/05/2019 10:01]
[15/05/2019 10:03]
[15/05/2019 10:05]

now considered StartTime as [15/05/2019 10:01] and EndTime as [15/05/2019 10:05]

2) now Considered 2nd list again, and select the second item

[StartTime=15/05/2019 10:42,EndTime=15/05/2019 10:48]

and check below timings in the second list first end time to second list 2nd starttime, that need to be a result like

[15/05/2019 10:30]
[15/05/2019 10:35]
[15/05/2019 10:38]

now considered StartTime as [15/05/2019 10:30] and EndTime as [15/05/2019 10:38]..

Similarly, we follow the next steps.

Thanks

  • 2
    It's unclear how the 2 first list can give the 2nd. I will recommend reading [ask]. Reduce the input exemple and explain the algo used to compute it. – xdtTransform May 15 '19 at 11:40
  • I think the OP is looking for a method that excludes from the first list all the datetime that are included in the elements range from second list – Steve May 15 '19 at 11:41
  • @xdtTransform it look like he want the range from first list that dosn't exist in second list. – Yair I May 15 '19 at 11:41
  • Is the result obtain by removing all date that where in the 2nd list range? if it's the case then [check if the date are in the range](https://stackoverflow.com/questions/4781611/how-to-know-if-a-datetime-is-between-a-daterange-in-c-sharp). and either add a not `!` or expect the list – xdtTransform May 15 '19 at 11:42
  • Anyway: See the [ask] help page and [The perfect question](http://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/) blog post by Jon Skeet. – Steve May 15 '19 at 11:42
  • the solution boils down to FirstList.Where(dateToCheck => !SndList.Any(y=> dateToCheck >= startDate && dateToCheck < endDate)), Item in list 1 that does not verryfy the statement: "date is in one of the range of list2". – xdtTransform May 15 '19 at 11:45
  • @YairI, either that or seeded random to have the correct index. But it's the first is the between date inclusive or not? – xdtTransform May 15 '19 at 11:46
  • Your code is not valid C# - please create a usable [mcve] we can work with. – Patrick Artner May 15 '19 at 11:46
  • 10h01, 10h03, 10h05, 10h30 are the first value that are not in a range. But by your result is [10h01, 10h05] and not [10h01, 10h03], [10h05, 10h30]. From the 12 result that are not in range how do you reduce it to your expected result? If it's the first and the last before a range, how do you handle the case where first and last are the same? Imagine you had only one date Superior to the first range. – xdtTransform May 15 '19 at 12:07
  • Could you just clarify what is expected when there is only one date, how do you make a range with only one date? Imagine if there was only `[15/05/2019 10:01]` before the first range – xdtTransform May 15 '19 at 12:54
  • a single time is not possible for my scenario. we have always multiple time in a day – Suresh Sankar May 15 '19 at 13:10
  • Multiple time in a day doesn't mean that you will have multiple date between two range . `[15/05/2019 10:01] [15/05/2019 10:03] [15/05/2019 10:05] [15/05/2019 10:09] [15/05/2019 10:11] [15/05/2019 10:19] [15/05/2019 10:22] [15/05/2019 10:28] [15/05/2019 10:30]` only the last one is Superior to the first range. – xdtTransform May 15 '19 at 13:55

2 Answers2

0

With a clear question and description everything is easy.

1/. For each date in your range you will select date that are:
- inferior to the starting date and - superior to the previous range date.
Starting with the lowest possible value as inferior bound.
2/. Order the result.
3/. If you have more than one result take the first and the last as new date range.

Code:

var result = new List<Foo>();
var lastLowerBound = DateTime.MinValue;
foreach (var range in List2)
{
    var filteredDates = List1.Where(d => d >= lastLowerBound && d <= range.StartTime)
                             .OrderBy(x => x);
    if (filteredDates.Count()> 1)
    {
        result.Add(
            new Foo { 
                StartTime = filteredDates.First(), 
                EndTime = filteredDates.Last()
        });
    }
    else
    {
        //How to make a date range if there is only one date?
    }
    lastLowerBound = range.EndTime;
}

You have populated your result with the range inferior to your filter range. Leaving only one range the last one. When the data is superior to the last range.

At this point you can repeat the work outside of the foreach.

var filteredDates = List1.Where(d => d > lastLowerBound)
                        .OrderBy(x => x).First();

if (filteredDates.Count() > 1)
{
    result2.Add(new Foo { StartTime = filteredDates.First(), EndTime = filteredDates.Last() });
}   

public class Foo
{
    public DateTime StartTime { get; set; }
    public DateTime EndTime { get; set; }
}

NB : A lot of optimisation can be done. It was just the simpliest algo based on OP description. An exemple on how to translate english to code.

xdtTransform
  • 1,986
  • 14
  • 34
  • StartTime : 5/15/2019 10:01:00 AM EndTime : 5/15/2019 10:05:00 AM StartTime : 5/15/2019 10:01:00 AM EndTime : 5/15/2019 10:42:00 AM StartTime : 5/15/2019 10:01:00 AM EndTime : 5/15/2019 11:18:00 AM this is not my expectation result. – Suresh Sankar May 15 '19 at 13:11
  • No Ide just using phone browser to type on online IDE.Simple debugger will show you that I "forgot" to set the `lastLowerBound = range.EndTime;`. And the last range that was not in your walkthough of the algo. Online demo as been removed as it's a pain to edit. But the code works. – xdtTransform May 15 '19 at 13:54
  • Thanks for your response.we got the expected result. – Suresh Sankar May 16 '19 at 07:13
0

Normally I would do this with some extension methods that make it easier, but here is a standard LINQ solution. Assume your first List is src and your second List is rangeBreaks, and rangeBreaks is sorted properly.

Then you can create a new list of the intervals you want to find by zipping the rangeBreaks itself skipping the first, so you can combine the EndTime of one with the StartTime of the next:

var gaps = new[] { new { DateTime.MinValue, MaxValue = rangeBreaks[0].StartTime } }
                .Concat(rangeBreaks.Zip(rangeBreaks.Skip(1), (f, s) => new { MinValue = f.EndTime, MaxValue = s.StartTime }))
                .Concat(new[] { new { MinValue = rangeBreaks.Last().EndTime, DateTime.MaxValue } });

With that, it is easy to break the src List into groups that fit in each gap, and then use the first and last of each gap to create a new interval record.

var ans = gaps.Select(g => src.Where(s => g.MinValue < s && s < g.MaxValue).ToList())
              .Select(gl => new { StartTime = gl.Min(), EndTime = gl.Max() });

Note: If src is ordered, you could use First() and Last() instead of Min() and Max().

NetMage
  • 26,163
  • 3
  • 34
  • 55