Search code examples
c#asp.net-mvcobjectarraylist

C# Add List class to new List class without looping


I have a list of users returned in a class

My Class: List

public class EmployeeList
{
    public int Emp_No { get; set; }
    public string Sys_Prefix { get; set; }
    public short Company_No { get; set; }
    public string Surname { get; set; }
    public string First_Name { get; set; }
    public string Known_As { get; set; }
    public string Initials { get; set; }
    public string Title { get; set; }
}

without looping through the results of this class i want to add the results to a new list var newsFeedEmps = new List<NewsFeedEmployees>();

public partial class NewsFeedEmployees
{
    public long Company_No { get; set; }
    public long Emp_No { get; set; }
    public long SourceId { get; set; }
    public string Sys_Prefix { get; set; }

    public long NewsFeedID { get; set; }

    public bool isActive { get; set; }
}

I cant use newsFeedEmps.AddRange(EmployeeList) because not all the parameters match and i will be assigning a separate value to NewsFeedID and isActive for the full list

I don't want to use a foreach loop to loop through the first list and do a newsFeedEmps.Add(new .... ) I found a separate post mentioning

Queue<NewsFeedEmployees> myQueue = new Queue<NewsFeedEmployees>();
myQueue.EnqueueRange(emps.Select(emp => new NewsFeedEmployees()
{
    Company_No = emp.Company_No,
    Emp_No = emp.Emp_No,
}));

But i get an error that Queue does not contain a definition for EnqueueRange


Solution

  • You can do this in various ways without an explicit for loop, but if the goal is

    trying to reduce time taken

    I'm quite confident that you can't do better than O(n) (actually θ(n)).

    Here's a way you can avoid an explicit for loop. If you want to go with something already built in, you can write the operation like this:

    Queue<NewsFeedEmployees> myQueue = new Queue<NewsFeedEmployees>();
    emps.Select(emp => new NewsFeedEmployees
        {
            Company_No = emp.Company_No,
            Emp_No = emp.Emp_No,
        })
        .ToList()
        .ForEach(myQueue.Enqueue);
    

    Unfortunately, ForEach is only available on List<T>, which is why ToList() is required.

    This actually loops through emps twice, but still has θ(n) running time.

    You might think, then, that you could write your own ForEach extension method directly on IEnumerable<T>, and while you can, as Eric Lippert explains, there's not much point in doing that.

    If, however, we assume that emps is already a List<EmployeeList> you could also do this:

    Queue<NewsFeedEmployees> myQueue = new Queue<NewsFeedEmployees>();
    emps.ForEach(emp => myQueue.Enqueue(new NewsFeedEmployees
        {
            Company_No = emp.Company_No,
            Emp_No = emp.Emp_No,
        }));
    

    This, at least, only implicitly loops through emps once. It's still θ(n), although it's theoretically twice as fast as the previous suggestion.

    In any case, List<T>.ForEach loops through the list once, and I feel confident stating that you can't do better than that.

    In a language like F# or Haskell, one could implement the same kind of operation with recursion instead of explicit loops, but it would still be an θ(n) operation.

    Ultimately, though, unless you have millions of records, don't worry. As Rob Pike stated,

    n is usually small.