使用字典代替List - 获取ith条目

时间:2014-12-10 15:53:54

标签: c# dictionary while-loop

也许我现在只是在愚蠢的时刻。我有以下内容:

List<DirectoryEntry> list = new List<DirectoryEntry>();
List.Add(startEntry);
int i=0;
while(i < list.Count) {
    DirectoryEntry entry = list[i];
    foreach(DirectoryEntry child in GetChildEntries(entry)) {
        if(!list.Contains(child)) // Do not add if entry already in list!
            list.Add(child);
    }
}

这不起作用,因为Contains以两种方式为指向同一AD对象的directoryEntries返回false。

所以我想从中创建一个Dictionary并将distinguishedName与条目一起存储:

Dictionary<string,DirectoryEntry> list = new Dictionary<string,DirectoryEntry>();
List.Add(startEntry.Properties["distinguishedName"].Value,startEntry);
int i=0;
while(i < list.Count) {
    DirectoryEntry entry = list[i]; // Does not work, because the index is a string here.
                                    // How to get the ith entry from the dictionary?
    foreach(DirectoryEntry child in GetChildEntries(entry)) {
        var dn = child.Properties["distinguishedName"].Value;
        if(!list.ContainsKey(dn)) list.Add(dn,child);
    }
}

问题,如代码注释中所述:

如何从词典中获取第i个条目?

4 个答案:

答案 0 :(得分:6)

可以使用list.ElementAt(i)按照发生的顺序获取i th 元素以便字典返回 - 但不保证订单是什么,或者它会随着时间的推移保持一致。我强烈建议避免认为字典有任何订单概念。

在我看来,你只需要迭代字典:

foreach (var entry in list)
{
    ...
}

这会导致另一个问题,那就是你正在修改你正在迭代的集合,而你正在迭代它,这将失败。您可能需要考虑在迭代时创建 new 字典,然后将所有条目添加到原始字典中。

目前还不清楚你是否真的想要一本字典。我们不知道你真正想要实现的目标 - 这里有很多不同的选择。

编辑:如果你想要变平,你可以做类似的事情:

var entries = new Dictionary<string, DirectoryEntry>();
var queue = new Queue<DirectoryEntry>();
queue.Enqueue(startEntry);
while (queue.Count > 0)
{
    var candidate = queue.Dequeue();
    string key = candidate.Properties["distinguishedName"].Value;
    if (!entries.ContainsKey(key))
    {
        entries[key] = candidate;
        foreach (var child in GetChildEntries(candidate))
        {
            queue.Enqueue(child);
        }
    }
}

如果您愿意,可以在foreach上创建自己的EnqueueAll扩展程序来“隐藏”Queue<T>循环。

这让我感觉更容易理解,而不是迭代你仍在添加的集合。

编辑:如果您以后不需要使用专有名称查找,则可以HashSet<DirectoryEntry>使用custom equality comparer

var entries = new HashSet<DirectoryEntry>(new DirectoryEntryEqualityComparer());
var queue = new Queue<DirectoryEntry>();
queue.Enqueue(startEntry);
while (queue.Count > 0)
{
    if (entries.Add(candidate))
    {
        foreach (var child in GetChildEntries(candidate))
        {
            queue.Enqueue(child);
        }
    }
}

答案 1 :(得分:2)

不订购字典。你这里不需要字典。您只需要覆盖类中的GetHashCodeEquals方法,以便Contains方法知道如何比较两个DictionaryEntry。或者如果您想要比较它们在一个属性上你可以使用linq:

if(!list.Any(x => x.SomeProp == child.SomeProp)) 
        list.Add(child);

答案 2 :(得分:1)

你无法从字典中获得第i个条目。字典不是列表也不是数组,它是字典。这些项目存储在哈希中(不一定按顺序)。想象一下,如果你拿了一个项目列表,然后删除了前一个和下一个项目的所有链接,然后散列这些项目。这就像字典一样。

答案 3 :(得分:1)

list.Values.ElementAt(n)的

(记得是'使用System.Linq')