Каков наиболее эффективный способ объединения элементов одного типа в общий список в C #? - PullRequest
3 голосов
/ 21 июля 2010

Например, у меня есть следующие интерфейс и классы:

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;}
}

Если общий список содержит следующие элементы:

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

И я объединю те же типы, объединю «С / До» и сожму элементы в списке, чтобы получился результат:

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])

Пожалуйста, убедитесь, что вы понимаетевопрос, прежде чем ответить, поскольку у меня есть история неоднозначности, и я не хочу расстраивать людей.Поэтому, пожалуйста, прокомментируйте, если вы чувствуете, что «требование» неясно.

Мой путь немного туп:

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

Мне просто интереснодолжно быть лучшее решение.

Обновлено:

Я просто понимаю, что мое "тупое решение" не будет охватывать случаи, как более 2 непрерывных предметов одного типа.

Пример:

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();

Ответы [ 4 ]

3 голосов
/ 21 июля 2010

Я написал в блоге об этом :-).

Это похоже почти на 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, которые рассчитываются как минимальное / максимальное время из собранной группы.

2 голосов
/ 21 июля 2010

Я не думаю, что ваш псевдокод вообще глуп, если он работает так, как вы ожидаете. Я не верю, что вы найдете легкий путь к тому, что вы пытаетесь сделать, поскольку это довольно необычный алгоритм. Итог: если этот алгоритм не будет запускаться миллионы раз в день и в списке нет миллионов объектов, я бы не стал беспокоиться об эффективности.

1 голос
/ 21 июля 2010
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
}
0 голосов
/ 21 июля 2010

Я считаю, что это очень специфическая вещь.Я не уверен, будет ли это поддерживаться фреймворком в любом случае.Что произойдет, если тип не получен из IRole напрямую.Что делать, если есть что-то вроде IEmployee, из которого происходит IManager.Я не уверен, как структура приложения может быть понята с помощью фреймворка.

Если вопрос очень специфичен для приложения, вы можете использовать linq, чтобы сделать это с помощью предложения group (on type).Я не пробовал этого раньше, поэтому не могу дать вам точное решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...