2

I searched some links here to change nested loops to single Linq, I tried using those, part of code is not working, I need some expert guidance to fix this,

UPDATE 1:

I guess wasn't clear in my explanation, the loops works fine! as expected, I am getting correct results, but I am doing optimization, instead of using two loops i need the same code to be converted to single linq.

here is the code :

foreach (var ob in all_request_list.Where(x => x.StartDate != x.EndDate)) {
    int consq_dates = ob.EndDate.DateDiff(ob.StartDate);                
    for (int i = 0; i <= consq_dates; i++) {
        combined_list.Add(new { ShiftID = ob.ShiftID, SkillID = ob.SkillID, EmployeeID = ob.EmployeeID, AssignDate = ob.StartDate.AddDays(i), ProfileID = ob.ProfileID });
    }
}

I have problem adding increment variable i to ob.StartDate.AddDays(i).

any help will be appreciated.

Manjuboyz
  • 6,978
  • 3
  • 21
  • 43
  • What error do you get? What are the types handled by `combined_list`? I'm pretty sure that you can't add the anonymous type that you're using in `Add` call to that list. The only ways may be a `List` or `List`. Maybe that's the problem. – Sebastian Schumann Aug 24 '16 at 05:12
  • why would you ever want to add 0 days to a date? – Neil Aug 24 '16 at 05:21
  • 1
    @Neil To start at that day maybe (Inclusive range) – Zein Makki Aug 24 '16 at 05:22
  • Have updated the explanations, please have a look at it. – Manjuboyz Aug 24 '16 at 05:28
  • @Neil, add 0 will take the current day. the above code works absolutely fire, there are no errors, I need to optimize the code using linq. – Manjuboyz Aug 24 '16 at 05:29
  • @Manjuboyz I did not expect it to break. – Neil Aug 24 '16 at 05:31
  • _...the loops works fine! as expected_. Changing `for` loops to `LINQ` will not affect on performance. Pure `for` loops is always faster then `LINQ` version of same loop and in some cases `LINQ` can worse readability – Fabio Aug 24 '16 at 05:42
  • What kind of optimization you are looking for? It is very unlikely to get Linq code to be faster than regular loop. So clearly you are not looking for speed... But what else? – Alexei Levenkov Aug 24 '16 at 05:46

3 Answers3

4

Is this what you're looking for?

var items = from ob in all_request_list
            where ob.StartDate != ob.EndDate
            let consq_dates = ob.EndDate.DateDiff(ob.StartDate)
            from i in Enumerable.Range(0, consq_dates + 1)
            select new { ShiftID = ob.ShiftID, SkillID = ob.SkillID, EmployeeID = ob.EmployeeID, AssignDate = ob.StartDate.AddDays(i), ProfileID = ob.ProfileID };
combined_list.AddRange(items);

But: You've code that works. You understand that code. Why do you wan't to change that? BTW: Your two loops will be faster than that linq.

Sebastian Schumann
  • 3,204
  • 19
  • 37
2

You can use the following Linq:

var items = all_request_list
    .Where(x => x.StartDate != x.EndDate)
    .SelectMany(x => Enumerable.Range(0, x.EndDate.DateDiff(x.StartDate) + 1)
        .Select(y => new { ShiftID = x.ShiftID, SkillID = x.SkillID, EmployeeID = x.EmployeeID, AssignDate = x.StartDate.AddDays(y), ProfileID = x.ProfileID }))

combined_list.AddRange(items);

What it does exactly is Creating an IEumerable<> of results for each item in the all_request_list.Where using Enumerable.Range (This is the part which replaces your for loop), than flattens it using the SelectMany method.

It might be better than a for loop in the terms of readability/maintainability but keep in mind that Linq usually slower than plain loops (tl;dr: Understand what Linq does internally and what it will do in your case).

Community
  • 1
  • 1
Tamir Vered
  • 10,187
  • 5
  • 45
  • 57
0

I don't know exactly what error you're getting, but it could be due to the fact that certain functions cannot be executed inside a linq statement, since it internally translates it to sql. Try this:

foreach (var ob in all_request_list.Where(x => x.StartDate != x.EndDate))
        {
            int consq_dates = ob.EndDate.DateDiff(ob.StartDate);                
            for (int i = 0; i <= consq_dates; i++)
            {
                var newDate = ob.StartDate.AddDays(i);
                combined_list.Add(new { ShiftID = ob.ShiftID, SkillID = ob.SkillID, EmployeeID = ob.EmployeeID, AssignDate = newDate , ProfileID = ob.ProfileID });
            }
        }

If it still gives you an error, could you specify what error you're receiving, such as the name, type, etc.

Keyur PATEL
  • 2,299
  • 1
  • 15
  • 41
  • How do you know that it will be translated into SQL? OP doesn't say anything about SQL or databases. – Sebastian Schumann Aug 24 '16 at 05:19
  • What they mean is that LINQ gets translated into an expression. Imagine trying to write a for loop inside the expression block of an if statement `if(for(...)) { }`. The compiler wouldn't accept it. LINQ expressions are the same thing, just really spread out. – Soviut Aug 24 '16 at 05:30