题 从.NET HashSet中按索引选择元素


目前我正在使用派生自的自定义类 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 是一组文档集合的集合。文档按主题相似性分组。因此,该算法的最后一步是发现每个群集的标签。但算法并不完美,有时它会使两个或多个具有相同标签的聚类。我想要做的只是将这些集群合并为一个集群。


11
2017-09-30 08:29


起源




答案:


一般不会设置  索引。如果位置对您很重要,那么您应该使用a List<T> 而不是(或可能是一组)。

现在 SortedSet<T> 在.NET 4中略有不同,因为它维护一个排序的值顺序。但是,它仍然没有实现 IList<T>,所以通过索引访问 ElementAt 会很慢。

如果您可以提供有关您希望此功能的更多详细信息,那么它会有所帮助。你的用例目前还不是很清楚。


16
2017-09-30 08:33



我已经添加了更详细的问题描述,因为你问:) - Ventus
@Ventus:这并没有真正解释为什么你需要索引。如果你只是想为每个匹配项运行一个方法,那么一个简单的foreach循环肯定是前进的方向......你有特殊的理由想要一个索引吗? - Jon Skeet
显然我的语言技能(我的意思是英语)并不完美,虽然我想同时修改集合中的2个元素。但是,你的建议是使用 List 而不是设置是好主意,所以问题解决了,你的答案被接受了。 - Ventus
你说“如果位置对你很重要,你应该使用a List<T>“但是,如果我想在我的收藏和订单中添加唯一条目怎么办? - whiteshooz
@whiteshooz:然后保持两个 HashSet<T> 和a List<T>,并保持同步。我不相信BCL中有任何可以保证保持位置的设置。 - Jon Skeet


如果您在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 

6
2018-05-23 20:07



这样安全吗?我认为,当您向HashSet添加元素时,可能会重新排序项目,并且后续对ToList()的调用可能并不总是产生相同的顺序。这只是一种预感,我没有看过代码和MSDN没有透露太多。 - uriDium
@uriDium定义“安全”。关键不在于后续调用保持相同的顺序,而只是执行具有某些对象的函数。 - Wolfzoon


没有带散列集的索引。散列集在某些情况下获得效率的方法之一是不必维护它们。

我也看不出这里有什么优势。如果你要获得索引,然后使用它,这将比获取元素效率低(获得索引同样有效,然后你有一个额外的操作)。

如果要对同一对象执行多个操作,只需按住该对象即可。

如果你想对几个对象做一些事情,那么在迭代它们的基础上这样做(正常 foreach 或做 foreach 关于结果 Where() 等等。)。如果你想在几个对象上做一些事情,然后在那些几个相同的对象上做一些其他事情,你必须在这样的批次中做,而不是在同一个对象中做所有的操作 foreach 然后存储结果 Where() 在一个 List<T>


3
2017-09-30 09:08