Почему-то я не думаю, что LINQ действительно предназначался для двунаправленного одномерного поиска в глубину, но я создал работающий LINQ с использованием Aggregate. Для этого примера я собираюсь использовать список вместо массива. Кроме того, я собираюсь использовать Activity
для ссылки на любой класс, в котором вы храните данные. Замените его тем, что подходит для вашего кода.
Прежде чем мы начнем, нам нужна небольшая функция для обработки чего-либо. List.Add(T)
возвращает ноль, но мы хотим иметь возможность накапливаться в списке и возвращать новый список для этой агрегатной функции. Поэтому все, что вам нужно, это простая функция, подобная следующей.
private List<T> ListWithAdd<T>(List<T> src, T obj)
{
src.Add(obj);
return src;
}
Сначала мы получаем отсортированный список всех действий, а затем инициализируем список связанных действий. Этот начальный список будет содержать только целевую активность, чтобы начать.
List<Activity> orderedEvents = activities.OrderBy(a => a.ActivityDate).ToList();
List<Activity> relatedActivities = new List<Activity>();
relatedActivities.Add(activity);
Мы должны разбить это на два списка: прошлое и будущее, как вы это делаете сейчас.
Начнем с прошлого, конструкция должна выглядеть в основном знакомой. Затем мы сгруппируем все это в связанные действия. Здесь используется функция ListWithAdd
, которую мы написали ранее. Вы можете сжать его в одну строку и пропустить объявление предыдущегоEvents как его собственной переменной, но я оставил его отдельно для этого примера.
var previousEvents = orderedEvents.TakeWhile(a => a.ID != activity.ID).Reverse();
relatedActivities = previousEvents.Aggregate<Activity, List<Activity>>(relatedActivities, (items, prevItem) => items.OrderBy(a => a.ActivityDate).First().ActivityDate.Subtract(prevItem.ActivityDate).Days.Equals(1) ? ListWithAdd(items, prevItem) : items).ToList();
Далее мы скомпилируем следующие события аналогичным образом и аналогично скомпилируем их.
var nextEvents = orderedEvents.SkipWhile(a => a.ID != activity.ID);
relatedActivities = nextEvents.Aggregate<Activity, List<Activity>>(relatedActivities, (items, nextItem) => nextItem.ActivityDate.Subtract(items.OrderBy(a => a.ActivityDate).Last().ActivityDate).Days.Equals(1) ? ListWithAdd(items, nextItem) : items).ToList();
После этого вы можете правильно отсортировать результат, так как теперь связанные действия должны содержать все действия без пробелов. Это не сразу сломается, когда он достигнет первого разрыва, нет, но я не думаю, что вы можете буквально вырваться из LINQ. Поэтому вместо этого он просто игнорирует все, что находит за пропуском.
Обратите внимание, что этот пример кода работает только с фактической разницей во времени. Ваш примерный вывод подразумевает, что вам нужны некоторые другие факторы сравнения, но этого должно быть достаточно, чтобы начать работу. Просто добавьте необходимую логику к сравнению вычитания даты в обеих записях.