访问“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&lt;TSource&gt; 方法通过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&lt;T&gt; 实现来强制唯一性,就像 SorteSet&lt;T&gt; 所做的那样(忽略集合中已经存在的元素的添加) .使用List&lt;T&gt; 作为后备存储。按排序顺序维护它,以便您可以使用二进制搜索来确定要添加的元素是否已经存在。或者,只需子类型 List&lt;T&gt; 并覆盖适当的方法以获得您想要的语义。

【讨论】:

感谢您解释通过ElementAt() 访问SortedSet 的成员所招致的惩罚。你能提供一个更有效的问题的答案吗? @DavidRR:查看我修改后的答案。 本着长期代码维护成本的精神,许多人认为直接使用供应商的 API 通常比编写自定义代码更可取,当供应商的 API 满足要求时。 (要求可以包括运行时性能。)也就是说,一个人的代码当然应该记录在案,以表明性能下降的可能性。 Microsoft 包含 Enumerable.ElementAt() 是有原因的……当然在某些场合它既方便又理想! @DavidRR 是的,但我在概念上不喜欢ElementAtIEnumerable&lt;T&gt;s,因为IEnumerable&lt;T&gt; 没有执行特定的顺序。例如,ElementAtLast 等方法对HashSet&lt;T&gt; 没有意义。不过,您可以实现 IndexedSortedSet&lt;T&gt; 以避免查找损失,但这也意味着您会降低 AddRemove 的性能。【参考方案3】:

如果您打算将数据加载到集合中,然后访问该集合,请使用HashSetImmutableSortedSet 而不是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数据中指定位置的多个数据行

如何在word中指定范围,在指定位置自动生成目录?