2010-09-30 3 views
8

На данный момент я использую собственный класс, полученный из HashSet. Там есть точка в коде, когда я выбираю пункты при определенных условиях:Выберите элемент по индексу из .NET HashSet

var c = clusters.Where(x => x.Label != null && x.Label.Equals(someLabel));

Он отлично работает, и я получаю эти элементы. Но есть ли способ получить индекс этого элемента в коллекции для использования с методом ElementAt вместо целых объектов?

Это будет выглядеть более или менее так:

var c = select element index in collection under certain condition; 
int index = c.ElementAt(0); //get first index 
clusters.ElementAt(index).RunObjectMthod();

вручную итерацию по всей коллекции лучше? Мне нужно добавить, что это в большем цикле, поэтому это предложение Where выполняется несколько раз для разных строк someLabel.

Редактировать

Что мне нужно? clusters представляет собой набор кластеров некоторых документов. Документы сгруппированы в кластеры по сходству тем. Таким образом, одним из последних шагов алгоритма является обнаружение метки для каждого кластера. Но алгоритм не совершенен, и иногда он создает два или более кластера с одной и той же меткой. Я хочу просто объединить эти кластеры в большие.

ответ

14

Наборы, как правило, имеют индексы. Если позиция важна для вас, вы должны использовать List<T> вместо (или, возможно, так же, как) набора.

В настоящее время SortedSet<T> в .NET 4 несколько отличается тем, что хранит упорядоченный порядок значений. Однако он все еще не реализует IList<T>, поэтому доступ по индексу с ElementAt будет медленным.

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

+0

Я добавил более подробное описание проблемы, как вы просили :) – Ventus

+0

@ Ventus: На самом деле это не объясняет, зачем нужен индекс. Если вы просто хотите запустить метод для каждого подходящего элемента, простой цикл foreach определенно является способом продвижения вперед ... у вас есть особая причина для желания индекса? –

+0

Очевидно, что мои языковые навыки (я имею в виду английский) не идеальны, хотя я хотел одновременно изменить два элемента в коллекции. Тем не менее, ваше предложение использовать «Список» вместо набора было хорошей идеей, поэтому проблема решена и ваш ответ принят. – Ventus

3

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

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

Если вы хотите выполнить несколько операций с одним и тем же объектом, просто держитесь за этот объект.

Если вы хотите сделать что-то на нескольких объектах, сделать это на основе итерацию через них (нормальный foreach или делать foreach по результатам Where() и т.д.). Если вы хотите что-то сделать на нескольких объектах, а затем сделать что-то еще на этих нескольких объектах, и вам нужно сделать это в таких партиях, вместо того чтобы выполнять все операции в одном и том же foreach, тогда сохраните результаты Where() в List<T>.

5

В случае, если вы храните элементы в HashSet, и иногда вам нужно получить элементы по индексу, рассмотрите возможность использования метода расширения ToList() в таких ситуациях. Таким образом, вы используете функции HashSet, а затем используете индексы.

HashSet<T> hashset = new HashSet<T>(); 

//the special situation where we need index way of getting elements 
List<T> list = hashset.ToList(); 

//doing our special job, for example mapping the elements to EF entities collection (that was my case) 

//we can still operate on hashset for example when we still want to keep uniqueness through the elements 
+1

Это безопасно? Я думаю, что при добавлении элементов в HashSet элементы могут быть переупорядочены, а последующие вызовы ToList() могут не всегда давать один и тот же порядок. Это просто догадка, я не смотрел на код, и MSDN ничего не показывал. – uriDium

+0

@uriDium Определить «безопасный». Дело было не в том, что последующие вызовы сохраняли один и тот же порядок, а просто для выполнения функции с некоторыми объектами. – Wolfzoon

Смежные вопросы