Re: Самая длинная непрерывная последовательность
От: SuhanovSergey  
Дата: 01.08.12 18:05
Оценка: 5 (3) +3 :))) :))
интервьювер: нужно написать Linq запрос, выбирающий самую длинную непрерывную последовательность

кандидат: как-то так

var maxElt = SplitToEqualRanges(s).Aggregate((Tuple<object, int>)null, (max, i) => max == null || i.Item2 > max.Item2 ? i : max);

 static IEnumerable<Tuple<T, int>> SplitToEqualRanges<T>(IEnumerable<T> sequence)
{
    T current = default(T);
    int currentLen = 0;
    foreach (var i in sequence)
    {
        if (currentLen == 0)
        {
            current = i;
        }
        else if (!current.Equals(i))
        {
            yield return new Tuple<T, int>(current, currentLen);
            current = i;
            currentLen = 0;
        }
        ++currentLen;
    }
    if (currentLen > 0)
        yield return new Tuple<T, int>(current, currentLen);
}


интервьювер: тут мало Linq-а и слишком императивно

кандидат: зато
— это понятнее, чем многоэтажный Linq
— гарантированно потребляет минимум ресурсов (O(1) памяти и O(n) времени)
— проходит по последовательно один раз, что позволяет передавать последовательности неизвестной заранее длины

интервьювер: чтобы пройти наш тест ваше решение должно содержать как минимум 5 Linq вызовов

кандидат: хорошо. Вот новое решение со всеми достоинствами предыдущего, и удовлетворяещее вашему требованию

var maxElt2 = 
    s.Zip(Enumerable.Range(0, s.Length), (elt, i) => new { Elt = elt, Idx = i })
    .ZipWithPrev()
    .Where(i => i.Item1.Idx == 0 || !i.Item1.Elt.Equals(i.Item2.Elt))
    .Select(i => i.Item1)
    .Concat(Enumerable.Repeat(new { Elt = (object)null, Idx = s.Length }, 1))
    .ZipWithPrev()
    .Skip(1)
    .Select(i => new {Elt=i.Item2.Elt, Len = i.Item1.Idx - i.Item2.Idx})
    .Aggregate((max, i) => max == null || i.Len > max.Len ? i : max);

static IEnumerable<Tuple<T, T>> ZipWithPrev<T>(this IEnumerable<T> s)
{
    T prev = default(T);
    foreach (var i in s)
    {
        yield return new Tuple<T, T>(i, prev);
        prev = i;
    }
}


интервьювер: совсем другое дело! хоть сейчас в продакшен!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.