0

I change my question. I want to know if with Linq can I get the same result as my code under. I have a folder with many pdf files. I need to group all files with date creation less then 10 seconds and merge these files.

I did the code but I want to know if I can do it with Linq.

My code is :

 _period = 10;


 DirectoryInfo di = new DirectoryInfo(_path);
 List<FileInfo> files = di.GetFiles().OrderByDescending(d => d.CreationTime).ToList();
  List<String> pdffiles = new List<String>();

  if (files.Count > 0)
  {
    DateTime previous = files.FirstOrDefault().CreationTime;
    TimeSpan delay = new TimeSpan(0, 0, _period);
    foreach (var file in files)
    {
      if (file.CreationTime - previous <= delay) 
        pdffiles.Add(file.FullName);
    }
  }

I want to know there is a way with Linq to get the same result without a loop? Hope my code is more explicit than my description.

Thank you. Karim.

Serkan Arslan
  • 13,158
  • 4
  • 29
  • 44
  • Linq *is* a loop, you just don't see it. – Maarten Jan 24 '18 at 10:23
  • @Gert The question title makes it look like a duplicate, but the text `here I compare previous and current files date creation, if under 10 seconds and I add it to pdffiles` makes it clear that the OP does not want grouping, the OP wants to compare the current item to the previous item. – Maarten Jan 24 '18 at 10:28
  • It's only possible to group files in fixed time buckets. If three files are in a 9s sequence, how should they be grouped? File 1 and 2 belong together, file 2 and 3 also, putting all files in one group. But file 1 and 3 are 18 s apart, so they can't be in one group. The grouping condition contradicts itself. Similar problem here: https://stackoverflow.com/a/37734601/861716 – Gert Arnold Jan 24 '18 at 10:33
  • I edit and change my question (hope it will be more explicit...sorry). In your example, I need to have a first group with file1 and 2 then a group with file 3. – karim harfakti Jan 24 '18 at 10:38
  • After the edit: OK, reopened, but I hope you're aware of the pitfalls here. Also: what makes a "LINQ solution" better than a loop? – Gert Arnold Jan 24 '18 at 10:39
  • Ok thank you for the link to the duplicate. – karim harfakti Jan 24 '18 at 10:43
  • It will help me a lot! ;) – karim harfakti Jan 24 '18 at 10:43

2 Answers2

2

You can use this.

string _path = @"C:\Temp";
int _period = 10;
TimeSpan delay = new TimeSpan(0, 0, _period);

DirectoryInfo di = new DirectoryInfo(_path);
var files = di.GetFiles()
              .OrderByDescending(d => d.CreationTime)
              .Select((d, i) => new { File = d, Index = i }).ToList();

List<String> pdffiles = files.Join(files, f1 => f1.Index, f2 => f2.Index - 1, (f1, f2) => new { f1, f2 })
                            .Where(f => Math.Abs( f.f1.File.CreationTime.Subtract(f.f2.File.CreationTime).Seconds ) <= delay.Seconds)
                            .Select(f => f.f1.File.FullName)
                            .ToList();
Serkan Arslan
  • 13,158
  • 4
  • 29
  • 44
0

If I have understood correctly, you can try this...

string _path = @"C:\Temp";
int _period = 10;
TimeSpan delay = TimeSpan.FromSeconds(_period);
DirectoryInfo di = new DirectoryInfo(_path);

List<String> pdffiles = di.GetFiles().TakeWhile(f =>
    {
        if (maxDate == null)
        {
            maxDate = f.CreationTime.Subtract(delay);
        }
        return f.CreationTime >= maxDate;
    }).Select(f => f.FullName).ToList();
Nacho
  • 962
  • 6
  • 14