Индекс - это все, что вам действительно нужно:
db.temperature.ensureIndex({ 'station': 1, 'dt': 1 })
for s in db.temperature.distinct('station'):
db.temperature.find({ station: s }).sort({ dt : -1 }).limit(1)
, конечно, используя любой синтаксис, действительно действительный для вашего языка.
Edit: Вы правы, что такой цикл берет на себя поездку на одну поездку, и это отлично подходит для нескольких станций, и не очень хорошо для 1000. Однако вы все же хотите использовать составной индекс на станции + dt и использовать нисходящую сортировку:
db.temperature.aggregate([
{ $sort: { station: 1, dt: -1 } },
{ $group: { _id: "$station", result: {$first:"$dt"}, t: {$first:"$t"} } }
])
С ArrayList Вы справедливо ограничены, потому что нет никакого класса неуниверсального набора только для чтения в BCL. Быстрое и грязное решение состоит в том, чтобы возвратить тип IEnumerable.
public IEnumerable MyList
{
get { return mMyList;}
}
Это не будет на самом деле препятствовать тому, чтобы кто-то бросил в ArrayList, но он не позволит редактирования по умолчанию ни один
, можно возвратить эффективно список только для чтения путем вызова ArrayList. ReadOnly. Однако это - тип возврата, ArrayList, таким образом, пользователь все еще был бы в состоянии скомпилировать с.Add, но это произведет ошибку периода выполнения.
Используйте ArrayList. ReadOnly () метод, чтобы создать и возвратить обертку только для чтения вокруг списка. это не скопирует список, но просто сделает обертку только для чтения вокруг этого. Для получения времени компиляции, проверяя, Вы, вероятно, хотите возвратить обертку только для чтения как IEnumerable, как @Jared предполагает.
public IEnumerable MyList
{
get { return ArrayList.ReadOnly(mMyList); }
}
набор А, который только для чтения, является просто набором с оберткой, которая предотвращает изменение набора. Если изменения внесены в базовый набор, набор только для чтения отражает те изменения.
Этот метод является O (1) операция.
Только подробно остановиться на ответе JaredPar. Как он сказал, возвращение фактического поля поддержки не абсолютно безопасно, так как пользователь все еще в состоянии динамично бросить IEnumerable
назад к ArrayList
.
я записал бы что-то вроде этого, чтобы быть уверенным, что никакие модификации к исходному списку не сделаны:
public IEnumerable MyList
{
get
{
foreach (object o in mMyList)
yield return o;
}
}
С другой стороны, я был бы probabily также использовать универсальный список (IEnumerable<T>
), чтобы быть абсолютно безопасным с точки зрения типов.
Используйте ReadOnlyCollection
.
return new ReadOnlyCollection<object>(mMyList)
.
можно также сделать ReadOnlyCollection
поле, и оно автоматически отразит изменения в базовом списке. Это - наиболее эффективное решение.
, Если Вы знаете, что mMyList только содержит один тип объекта (например, он имеет только DateTimes), можно возвратиться ReadOnlyCollection<DateTime>
(или некоторый другой тип) для дополнительной безопасности типов. При использовании C# 3 можно просто записать
return new ReadOnlyCollection<DateTime>(mMyList.OfType<DateTime>().ToArray())
Однако, это автоматически не обновит с базовым списком и также менее эффективно (Он скопирует весь список). Наилучший вариант состоит в том, чтобы сделать mMyList дженериком List<T>
(например, List<DateTime>
)
Необходимо обернуть возвращаемое значение в набор только для чтения.
Просто сделайте свойство как Изолированное (или NotInheritable в VB.NET) и только для чтения, как это:
public sealed readonly ArrayList MyList
{
get { return mMyList;}
}
Также не забывают делать отступающее поле как только для чтения:
private readonly ArrayList mMyList;
, Но для инициализации значения mMyList, необходимо инициализировать его ТОЛЬКО в конструкторе, как в этом примере:
public SampleClass()
{
// Initialize mMyList
mMyList = new ArrayList();
}