访问“SortedSet”中指定索引处的项目
Posted
技术标签:
【中文标题】访问“SortedSet”中指定索引处的项目【英文标题】:Accessing the item at a specified index in a 'SortedSet' 【发布时间】:2014-01-08 14:45:48 【问题描述】:如何访问SortedSet
中指定索引(位置)的项目?
与SortedList
不同,SortedSet
不提供Item
property。
(另外,与SortedList
不同,SortedSet
强制其每个成员都是唯一的。也就是说,SortedSet
保证不包含重复项。)
【问题讨论】:
这是对 Microsoft 的功能请求github.com/dotnet/corefx/issues/4695 【参考方案1】:编辑: 一个普通的(无序的)集合,例如HashSet<T> 以没有特定的顺序管理它的元素。因此,无序集合中特定元素的索引没有任何特定含义。
然而,相比之下,通过 SortedSet<T> 中的位置(索引)请求元素在语义上是有意义的。否则,何必为有序集合的开销而烦恼呢?
也就是说,对于不关心性能的小型SortedSet<T>(参见下面的示例),Linq 扩展方法Enumerable.ElementAt() 提供了一种通过索引检索项目的便捷方法。但是,对于检索元素的运行时性能至关重要的大型 SortedSet<T>,请考虑按照 his answer 中的 @Nicholas Carey 大纲实现自定义集合。
原答案:
您可以通过Enumerable.ElementAt<TSource>
方法通过SortedSet
的索引(位置)访问感兴趣的项目:
var item = mySortedSet.ElementAt(index);
演示:
using System;
using System.Collections.Generic;
using System.Linq;
class SortedSetDemo
static void Main(string[] args)
var words = new string[]
"the", "quick", "brown", "fox", "jumps",
"over", "the", "lazy", "dog";
// Create a sorted set.
var wordSet = new SortedSet<string>();
foreach (string word in words)
wordSet.Add(word);
// List the members of the sorted set.
Console.WriteLine("Set items in sorted order:");
int i = 0;
foreach (string word in wordSet)
Console.WriteLine("0. 1", i++, word);
// Access an item at a specified index (position).
int index = 6;
var member = wordSet.ElementAt(index);
Console.WriteLine("\nThe item at index 0 is '1'!", index,
member);
预期输出:
The set items in sorted order is:
0. brown
1. dog
2. fox
3. jumps
4. lazy
5. over
6. quick
7. the
The item at position 6 is 'quick'!
【讨论】:
【参考方案2】:那是因为 SortedSet
has the semantics of a set 而不是 List
-like 构造。因此,它没有实现IList
(这使您能够通过Item
属性按索引处理项目)。
正如@DavidRR 所述,您可以使用Linq 扩展方法Enumerable.ElementAt()
。然而,由于SortedSet
的后备存储是红黑树——高度平衡的二叉树,通过ElementAt()
按索引访问元素涉及树遍历——O(N),最坏情况和 O( N/2) 的平均值,以获得所需的项目。与遍历单链表访问第 Nth 项几乎相同。
所以...对于大型集合,性能可能很差。
如果您想要的是一个提供类似数组语义的独特集合,为什么不推出您自己的 IList<T>
实现来强制唯一性,就像 SorteSet<T>
所做的那样(忽略集合中已经存在的元素的添加) .使用List<T>
作为后备存储。按排序顺序维护它,以便您可以使用二进制搜索来确定要添加的元素是否已经存在。或者,只需子类型 List<T>
并覆盖适当的方法以获得您想要的语义。
【讨论】:
感谢您解释通过ElementAt()
访问SortedSet
的成员所招致的惩罚。你能提供一个更有效的问题的答案吗?
@DavidRR:查看我修改后的答案。
本着长期代码维护成本的精神,许多人认为直接使用供应商的 API 通常比编写自定义代码更可取,当供应商的 API 满足要求时。 (要求可以包括运行时性能。)也就是说,一个人的代码当然应该记录在案,以表明性能下降的可能性。 Microsoft 包含 Enumerable.ElementAt()
是有原因的……当然在某些场合它既方便又理想!
@DavidRR 是的,但我在概念上不喜欢ElementAt
的IEnumerable<T>
s,因为IEnumerable<T>
没有执行特定的顺序。例如,ElementAt
、Last
等方法对HashSet<T>
没有意义。不过,您可以实现 IndexedSortedSet<T>
以避免查找损失,但这也意味着您会降低 Add
和 Remove
的性能。【参考方案3】:
如果您打算将数据加载到集合中,然后访问该集合,请使用HashSet
和ImmutableSortedSet
而不是SortedSet
。
将您的数据加载到HashSet
,然后调用ToImmutableSortedSet()
转换为可索引的不可变排序集。
【讨论】:
【参考方案4】:您可以使用MCollections 进行插入、编辑、删除、搜索和索引查找在 O(Lg(N)) 时间内,它使用 BST 并在每个节点中存储子节点的数量来访问项目指定索引
【讨论】:
这是我一直在寻找的很棒的图书馆。感谢分享。以上是关于访问“SortedSet”中指定索引处的项目的主要内容,如果未能解决你的问题,请参考以下文章
numpy使用[]语法索引二维numpy数组中指定指定列之前所有数据列的数值内容(accessing columns in numpy array before specifc column)
numpy使用[]语法索引二维numpy数组中指定指定行之后所有数据行的数值内容(accessing rows in numpy array after specifc row)
numpy使用[]语法索引二维numpy数组中指定指定行之前所有数据行的数值内容(accessing rows in numpy array before specifc row)
如何在 django 中指定索引类型? (btree 与哈希等)
pandas读取csv数据header参数指定作为列索引的行索引列表形成复合(多层)列索引使用iloc基于行索引位置列表筛选dataframe数据中指定位置的多个数据行