WraithNath
WraithNath

Reputation: 18013

How to remove first element from linq query

Im trying to consolidate a list of records of in and out times per day to the minimum number of records possible.

What i have done so far, is grouped up the lines into the groups they need to be in, and put the in and out times in a list for each day.

then i want to process the lists and add the first set of in and out lines onto a single line, then process the next entry and either create a new line or fill in the blanks of the previous line.

The bit im stuck with is removing the first item from the linq result after i have processed it.

happy to look at doing it a different way.

here is what i have:

       List<LoginRecordLine> condensedLoginRecordLines = new List<LoginRecordLine>();
       List<LoginRecordLine> currentLoginRecordLines = GetLoginRecordsForLoginRecordReport(lowerDate, upperDate, sageDatabaseID, loggedInUserID);

        var groupedLines = from LoginRecordLine line in currentLoginRecordLines
                           group line by new { line.TimesheetID, line.WorkPatternPayRateID } into g
                           select new
                           {
                               Lines = g,
                               TimesheetID = g.Key.TimesheetID,
                               PayRateID = g.Key.WorkPatternPayRateID
                           };

        foreach (var g in groupedLines)
        {
            var monTimes = from line in g.Lines
                           orderby line.MonTimeIn ascending
                           where line.MonTimeSpan != TimeSpan.Zero
                           select new
                           {
                               TimeIn = line.MonTimeIn,
                               TimeOut = line.MonTimeOut,
                               Timesheet = line.Timesheet,
                               PayRate = line.WorkPatternPayRate
                           };

            var tueTimes = //Same as monday

            var wedTimes = //Same as monday

            var thuTimes = //same as monday

            var friTimes = //same as monday

            var satTimes = //same as monday

            var sunTimes = //same as monday


            while (monTimes.Count() != 0 || tueTimes.Count() != 0 || wedTimes.Count() != 0 || thuTimes.Count() != 0 || friTimes.Count() != 0 || satTimes.Count() != 0 || sunTimes.Count() != 0)
            {
                LoginRecordLine condensedLine = new LoginRecordLine();

                if (monTimes.Count() >0)
                {
                    condensedLine.MonTimeIn = monTimes.First().TimeIn;
                    condensedLine.MonTimeOut = monTimes.First().TimeOut;
                    condensedLine.Timesheet = monTimes.First().Timesheet;
                    condensedLine.WorkPatternPayRate = monTimes.First().PayRate;

                    //*************** REVELANT PART *************/
                    //remove first item from monday list
                }

                // tue 

                // wed

                // etc
            }
        }

        return condensedLoginRecordLines;

Update - Working code - before performance changes

 List<LoginRecordLine> condensedLoginRecordLines = new List<LoginRecordLine>();

                List<LoginRecordLine> currentLoginRecordLines = GetLoginRecordsForLoginRecordReport(lowerDate, upperDate, sageDatabaseID, loggedInUserID);

                var groupedLines = from LoginRecordLine line in currentLoginRecordLines
                                   group line by new { line.TimesheetID, line.WorkPatternPayRateID } into g
                                   select new
                                   {
                                       Lines = g,
                                       TimesheetID = g.Key.TimesheetID,
                                       PayRateID = g.Key.WorkPatternPayRateID
                                   };

                foreach (var g in groupedLines)
                {
                    var monTimes = (from line in g.Lines
                                    orderby line.MonTimeIn ascending
                                    where line.MonTimeSpan != TimeSpan.Zero
                                    select new
                                    {
                                        TimeIn = line.MonTimeIn,
                                        TimeOut = line.MonTimeOut,
                                        Timesheet = line.Timesheet,
                                        PayRate = line.WorkPatternPayRate
                                    }).ToList();

            var tueTimes = //Same as monday

            var wedTimes = //Same as monday

            var thuTimes = //same as monday

            var friTimes = //same as monday

            var satTimes = //same as monday

            var sunTimes = //same as monday

                    while (monTimes.Count != 0 || tueTimes.Count != 0 || wedTimes.Count != 0 || thuTimes.Count != 0 || friTimes.Count != 0 || satTimes.Count != 0 || sunTimes.Count != 0)
                    {
                        LoginRecordLine condensedLine = new LoginRecordLine();

                        if (monTimes.Count >0)
                        {
                            condensedLine.MonTimeIn = monTimes.First().TimeIn;
                            condensedLine.MonTimeOut = monTimes.First().TimeOut;
                            condensedLine.Timesheet = monTimes.First().Timesheet;
                            condensedLine.WorkPatternPayRate = monTimes.First().PayRate;

                            condensedLoginRecordLines.Add(condensedLine);

                            monTimes.RemoveAt(0);
                        }

                        //etc
                    }
                }

                return condensedLoginRecordLines;

Upvotes: 0

Views: 13194

Answers (4)

Kiruahxh
Kiruahxh

Reputation: 2015

Use Skip function, ex:

int[] grades = { 59, 82, 70, 56, 92, 98, 85 };
Console.WriteLine("All grades except the first:");
foreach (int grade in grades.Skip(1))
    Console.WriteLine(grade);

Upvotes: 0

Brandon Barkley
Brandon Barkley

Reputation: 768

I came across a similar problem. In my case, the source data was a CSV file parsed into a string and I wanted to remove the header information before processing. I could have used the approach of casting to a list and removing the first entry, but I discovered that it is possible to add a second parameter to the where query that would give you the row number index. This works with both IQueryable and IEnumerable overloads as well.

public static List<string> GetDataLinesFromCSV(string csv)
{
    var csvLines = csv.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
    var dataLines = csvLines.AsQueryable().Where((x, idx) => idx > 0).ToList();
    return dataLines;
}

Upvotes: 0

galenus
galenus

Reputation: 2127

You should revise your algorithm and maybe data structures.

For anonymous types in queries I would add a DayOfWeek property, so the queries will look like:

var monTimes = from line in g.Lines
                       orderby line.MonTimeIn ascending
                       where line.MonTimeSpan != TimeSpan.Zero
                       select new
                       {
                           TimeIn = line.MonTimeIn,
                           TimeOut = line.MonTimeOut,
                           Timesheet = line.Timesheet,
                           PayRate = line.WorkPatternPayRate,
                           WeekDay = DayOfWeek.Monday
                       };

Then, the final loop will be replaced by something like:

var condensedLoginRecordLines = monTimes
   .Concat(tueTimes)
   .Concat(wedTimes)
   ..//etc
   .Select(data => new CondensedLine { WeekDay = data.WeekDay, /* here all the properties are initialized */ })
   .ToList();

And that's all.

If you still prefer to use the MonInTime, TueInTime, etc. properties, move the creation of CondensedLine into a separate function which applies a switch on the WeekDay and initializes the relevant properties only. In this case you should declare a private class instead the anonymous types you currently use in order to pass the information from method to another.

Upvotes: 0

Robson
Robson

Reputation: 926

use the List.RemoveAt Method something like myList.RemoveAt(0) will remove the first item of your list

Upvotes: 4

Related Questions