в .Чистая - qacode.ru" />

Реализация метода groupBy в .Чистая


Я реализовал метод groupBy метод расширения для IEnumerable в типа как задание на дип немного больше в технологии LINQ.

Что вы думаете об исходном коде?

Код:

static IEnumerable<IGrouping<TKey,TElement>> GroupBy<TKey,TElement>(this IEnumerable<TElement> source, Func<TElement,TKey> keySelector)
{
    //Grouping elements in the dictionary according to the criteria
    var dict = new Dictionary<TKey, List<TElement>>();

    //Filling the dictionary. It will contain: [Key -> List<Values>]
    foreach (var x in source)
    {
        var key = keySelector(x);
        if (dict.Keys.Contains(key))
        {
            dict[key].Add(x);
        }
        else
        {
            dict.Add(key, new List<TElement> { x });
        }
    }

    //For each group...
    foreach (var x in dict)
    {
        yield return new Grouping<TKey, TElement>(x.Key, x.Value);
    }
}

class Grouping<TKey, TElement> : IGrouping<TKey, TElement>
{
    private TKey _key;
    private IEnumerable<TElement> _elements;

    public Grouping(TKey key, IEnumerable<TElement> elements)
    {
        _key = key;
        _elements = elements;
    }

    public IEnumerator<TElement> GetEnumerator()
    {
        return _elements.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public TKey Key
    {
        get { return _key; }
    }
}


6286
8
задан 10 февраля 2011 в 10:02 Источник Поделиться
Комментарии
3 ответа

Если вы хотите дублировать метода groupBy семантика точно, есть несколько вещей, пропавших без вести:


  • Жаждущих ошибка проверки параметров вместо отложенных

  • Правильный порядок групп (метод groupBy гарантирует, что эти группы упорядочены в относительный порядок группы первого элемента в источнике)

  • Разрешая ключи, нуль

Вы можете быть заинтересованы в Джон Скит в последние записи блогов.

5
ответ дан 11 февраля 2011 в 04:02 Источник Поделиться

foreach (var x in dict)
{
yield return new Grouping<TKey, TElement>(x.Key, x.Value);
}

Может изменить на:

return dict.Select(x => new Grouping<TKey, TElement>(x.Key, x.Value));

Это мелочь, но я бы _key и _elements в группировку только для чтения.

3
ответ дан 10 февраля 2011 в 10:02 Источник Поделиться

Одна вещь, которая выделяется-это использование словаря. При проверке наличия и используя значение, вы должны использовать TryGetValue вот так:

List<TElement> tmpList;
if (!dict.TryGetValue(key, out tmpList))
{
dict.Add(key, tmpList = new List<TElement>());
}
tmpList.Add(x);

Также, в связи с изменением технологии LINQ упомянутых mjcopple, нет необходимости использовать выбрать; это менее эффективно и обеспечивает никакое преимущество над вашей доходности возврата в этом случае. Я бы поняла, если бы он даже повысят читабельность, но в данном случае это не так и я бы придерживаться первого решения ради эффективности.

Ничего страшного, но так как ты просто украшать перечисления элементов, вы могли бы также использовать это реализация неуниверсальных IEnumerable интерфейс, который позволит вам сэкономить метода в стеке вызовов (не сильно). Есть также вероятность, что базовая реализация более эффективна не универсального перечислителя, чем упаковка обычного (хотя это вообще редкость и не для списка)

IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_elements).GetEnumerator();
}

Стивен Клири делает соответствующие замечания относительно полноты своей реализации, так что я подумал, что просто выбросить указатели кода.

0
ответ дан 11 февраля 2011 в 03:02 Источник Поделиться