What is the most efficient way to merge items with the same type in a general list in C #?

Example: I have the following interface and classes:

public interface IRole {
    DateTime Since {get;}
    DateTime Until {get;}
}

public class Manager : IRole {
    public DateTime Since {get; private set;}
    public DateTime Until {get; private set;}
}
public class Employee : IRole {
    public DateTime Since {get; private set;}
    public DateTime Until {get; private set;}
}
public class Ceo: IRole {
    public DateTime Since {get; private set;}
    public DateTime Until {get; private set;}
}

If the general list contains the following items:

list[0]=new Manager();
list[1]=new Manager();
list[2]=new Employee();
list[3]=new Manager();
list[4]=new Ceo();
list[5]=new Ceo();

And I will combine the same types, combine C / C and compress the items in the list, so the output will be:

newList[0]=new Manager() //(Since is from list[0], Until is from list[1])
newList[1]=new Employee() //(list[2])
newList[2]=new Manager() //(list[3])
newList[3]=new Ceo() //(Since is from list[4], Until is from list[5])

Please make sure you understand the question before answering, because I have a story to be ambiguous and I do not want to upset people. Therefore, comment if you think the “requirement” is not clear.

My way is stupid:

for each item in list
    the current item shall always be merged into the previous item
        check if current item has the same type as the previous item
            get last item from newList and merge last item with current item

I'm just wondering what should be the best solution.

Updated:

I just understand that my “dumb decision” will not cover cases like more than two continuous elements of the same type.

Example:

list[0]=new Manager();
list[1]=new Manager();
list[2]=new Employee();
list[3]=new Manager();
list[4]=new Ceo();
list[5]=new Ceo();
list[6]=new Ceo();
+3
4

:-).

group by , . , . , group by LINQ, :

var groups =
  from person in list.WithAdjacentGrouping()
  group person by person.GetType().Name into g
  select new { 
    Type = g.Key,
    Since = new DateTime(g.Select(p => p.Since.Ticks).Min()),
    Until = new DateTime(g.Select(p => p.Until.Ticks).Max())
  }

WithAdjacentGrouping , . ( GetType().Name ).

, , (, "Ceo" ) - Since Until, / .

  • . LINQ WithAdjacentGrouping
+3

, , , . , , , . : , , .

+2
List<IRole> newList = new Lis<IRole>();
for (int i = 1; i < list.Count; i++) // Start at 1, so we can do i - 1 on the first iteration
{
  if (list[i - 1].GetType() != list[i].GetType()) // they're not the same
  {
    newList.Add(list[i - 1]); // so add the first one too
  }
  newList.Add(list[i]); // always add second one
}
+1

I think this is a very specific requirement. I am not sure that in any case this will be supported by the framework. What happens if the type is not directly derived from IRole. What if there is something like IEmployee from which IManager is derived. I'm not sure how specific applications can be understood by the framework.

If the question is very application specific, you can use linq to execute it using the group clause (by type). I have not tried this before, so I can not give you an exact solution.

0
source

Source: https://habr.com/ru/post/1755638/


All Articles