Вы просто создаете индексы на своей структуре, правильно?
>>> from collections import defaultdict
>>> def indexOn( things, pos ):
... inx= defaultdict(list)
... for t in things:
... inx[t[pos]].append(t)
... return inx
...
>>> a=[
... ['4', '21', '1', '14', '2008-10-24 15:42:58'],
... ['3', '22', '4', '2somename', '2008-10-24 15:22:03'],
... ['5', '21', '3', '19', '2008-10-24 15:45:45'],
... ['6', '21', '1', '1somename', '2008-10-24 15:45:49'],
... ['7', '22', '3', '2somename', '2008-10-24 15:45:51']
... ]
Вот Ваш первый запрос, сгруппированный положением 1.
>>> import pprint
>>> pprint.pprint( dict(indexOn(a,1)) )
{'21': [['4', '21', '1', '14', '2008-10-24 15:42:58'],
['5', '21', '3', '19', '2008-10-24 15:45:45'],
['6', '21', '1', '1somename', '2008-10-24 15:45:49']],
'22': [['3', '22', '4', '2somename', '2008-10-24 15:22:03'],
['7', '22', '3', '2somename', '2008-10-24 15:45:51']]}
Вот Ваш второй запрос, сгруппированный положением 3.
>>> dict(indexOn(a,3))
{'19': [['5', '21', '3', '19', '2008-10-24 15:45:45']], '14': [['4', '21', '1', '14', '2008-10-24 15:42:58']], '2somename': [['3', '22', '4', '2somename', '2008-10-24 15:22:03'], ['7', '22', '3', '2somename', '2008-10-24 15:45:51']], '1somename': [['6', '21', '1', '1somename', '2008-10-24 15:45:49']]}
>>> pprint.pprint(_)
{'14': [['4', '21', '1', '14', '2008-10-24 15:42:58']],
'19': [['5', '21', '3', '19', '2008-10-24 15:45:45']],
'1somename': [['6', '21', '1', '1somename', '2008-10-24 15:45:49']],
'2somename': [['3', '22', '4', '2somename', '2008-10-24 15:22:03'],
['7', '22', '3', '2somename', '2008-10-24 15:45:51']]}
В этом конкретном случае использование формы IEnumerable
будет более эффективным, потому что вам только нужно знать счетчик. Нет смысла сохранять данные, изменять размер буферов и т. Д., Если вам это не нужно.
Если вам нужно снова использовать результаты по какой-либо причине, форма List
будет более эффективной .
Обратите внимание, что как метод расширения Count ()
, так и свойство Count
будут эффективны для List
как реализация Count ()
проверяет, реализует ли целевая последовательность ICollection
, и использует свойство Count
, если это так.
Точный ответ на подобные вопросы может варьироваться в зависимости от множества факторов и может измениться в дальнейшем по мере развития среды CLR. Единственный способ быть уверенным - это измерить его - и имейте в виду, что если разница небольшая по сравнению с операцией, в которой она появится, тогда вам следует выбрать наиболее читаемый и поддерживаемый способ ее записи.
И на этом обратите внимание, вы также можете попробовать:
private IEnumerable<IObjectProvider> GetProviderForType1(Type type)
{
return _objectProviders.Where(provider =>
provider.Key.IsAssignableFrom(type) ||
type.IsAssignableFrom(provider.Key)) &&
provider.Value.SupportsType(type))
.Select(p => p.Value);
}
Вы также можете дать себе большую гибкость, вернув IEnumerable
, а затем используя метод расширения ToList
, если хотите "снимок" результатов в список.
Важная часть этого вопроса - «насколько велики данные»? Сколько строк ...
Для небольших объемов данных со списком все в порядке - выделение достаточно большого списка займет ничтожно мало времени, и его размер не будет изменяться много раз (нет, если вы можете сказать, насколько велик быть заранее).
Однако это не масштабируется для огромных объемов данных; кажется маловероятным, что ваш провайдер поддерживает тысячи интерфейсов, поэтому я бы не сказал, что переход на эту модель необходим , но это не сильно повредит.
Конечно, вы можете использовать LINQ. тоже:
return from provider in _objectProviders
where provider.Key.IsAssignableFrom(type) ...
select provider.Value;
Это также отложенный подход yield
под прикрытием ...