访问SortedList,它是另一个排序列表的值

时间:2014-04-01 16:01:06

标签: c# list

这可能是一个简单的问题,但我无法在任何地方找到答案!正如您所能说的那样,我对编码很新。

我目前正在开发一个项目,该项目使用SortedList存储字符串值作为其键,第二个SortedList作为其值。第二个SortedList有一系列数字ID(虽然存储为字符串)作为键,另一个字符串作为值。

我输入上面的值没有问题,但是我无法访问第二个SortedList,这是第一个的值。

我试图解决问题,希望有人能指出我正确的方向。

下面的示例(简化)代码......

//New and empty SortedLists created
SortedList mySL1 = new SortedList();
SortedList mySL2 = new SortedList();

//Clicking button1 first ensures mySL2 is clear and then adds a couple of KVPs
//Then text entered into a textBox and mySL2 are added as a KVP to mySL1
private void button1_Click(object sender, EventArgs e)
{
    mySL2.Clear();
    mySL2.Add("w", "x");
    mySL2.Add("y", "z");

    mySL1.Add(textBox1.Text, mySL2);
}

//Clicking button2 outputs each of the keys of mySL1 to a listBox
private void button2_Click(object sender, EventArgs e)
{
    for (int i = 0; i < mySL1.Count; i++)
    {
        listBox1.Items.Add(mySL1.GetKey(i));
    }
}

private void button3_Click(object sender, EventArgs e)
{
    for (int i = 0; i < mySL1.Count; i++)
    {

        //How do I access the KVPs of the mySL2 SortedLists which are the values of mySL1?

    }
}

修改

我怀疑我一直不清楚我在问什么,并且通过在我的简单代码中包含for循环来复杂一个相当简单的查询。 我遇到问题的是访问列表中列表的语法。

假设,如上例所示,我有一个排序列表(mySL1),其值是第二个排序列表(mySL2)。

在索引5处访问mySL1密钥的语法是mySL1.GetKey(5)

我试图找出的是访问mySL1特定索引的mySL2中特定键或值的语法,例如mySL2列表索引6处的键(值)at mySL1的索引5。 由于我可能想要访问mySL2中的特定键或值,因此foreach循环不够用。

1 个答案:

答案 0 :(得分:0)

新答案

好吧,我还不完全确定原始海报的内容是什么,但这是我的 最好猜测我到目前为止的信息:

private void button3_Click(object sender, EventArgs e)
{
    for (int i = 0; i < listOfLists.Count; i++)
    {
        var list = (SortedList) listOfLists.GetByIndex(i);

        for (int j = 0; j < list.Count; j++)
        {
            var key = (string) list.GetKey(j);
            var value = (string) list.GetByIndex(j);
        }
    }
}

您已经知道如何使用GetKey(i)在索引SortedList上获取i的密钥。 您还可以使用GetByIndex(i)获取该索引处的值。所有这些都可以在文档中找到,我建议您一直阅读它以查看是否有任何可以使用的内容。

旧答案

我会保留这个答案,以防它可能对原版海报有用。

您可以使用foreach循环将第二个列表的值作为KeyValuePairs获取:

var lists = new SortedList<string, SortedList<string, string>>
{
    {
        "foo",
        new SortedList<string, string>
        {
            { "0", "lol" },
            { "1", "skadoosh!" },
            { "2", "OMG!" }
        }
    }
};

foreach (var list in lists)
{
    foreach (var kvp in list.Value)
    {
        Console.WriteLine("({0}, {1})", kvp.Key, kvp.Value);
    }
}

首选通用集合到非通用集合

所以,上面有几点需要注意。我正在使用SortedList的通用版本,即SortedList<TKey, TValue>,因为如果您使用non-generic version,则在访问值时会获得更多类型安全检查。通过使用带有显式类型的通用版本,您可以避免显式转换类型,就像使用非泛型版本(its methods return type object)一样,如下所示:

var list = new SortedList();
list["foo"] = "bar";
string x = (string) list["foo"];

// vs generic

var list = new SortedList<string, string>();
list["foo"] = "bar";
string x = list["foo"];

如果可以,通常最佳做法是使用通用版本的集合。在大多数情况下,您应该避免使用非泛型集合,现在您可能只能在遗留代码中看到它们。

带有SortedList<TKey, TValue>

的foreach循环

好的,所以foreach循环允许您获取集合的值,而无需指定索引或键。那么SortedList<TKey, TValue>的价值是多少?值为KeyValuePair<TKey, TValue>

  1. SortedList<string, SortedList<string, string>>包含 KeyValuePair<string, SortedList<string, string>>

  2. SortedList<string, string>包含KeyValuePair<string, string>

  3. 因此,在第一个foreach循环中,您获得KeyValuePair<string, SortedList<string, string>>,并且您想要访问该对中的值列表:

    foreach (var list in lists)
    {
        foreach (var kvp in list.Value)
        {
            // Do stuff with kvp
        }
    }
    

    因此list.ValueSortedList<string, string>,其中包含(key, value)对更多字符串。因此,您只需使用kvp.Keykvp.Value访问每个键和值。

    var还是不要var?这就是问题:P

    您还可以通过明确指定项目类型而不是使用foreach来声明var循环:

    foreach (KeyValuePair<string, SortedList<string, string>> list in lists)
    {
        foreach (KeyValuePair<string, string> kvp in list.Value)
        {
            Console.WriteLine("({0}, {1})", kvp.Key, kvp.Value);
        }
    }
    

    您选择哪种款式取决于您,它们都是等价的。就个人而言,我只在类型明显时才使用var,否则很难说出正在使用的是什么类型,特别是如果你正在查看Visual Studio之外的代码,比如在Git diff或其他东西中。使用var而不是显式类型的另一个缺点是,您无法使用接口声明对象实例,如下所示:

    IDictionary<int, string> players = new SortedList<int, string>
    {
        { 0, "John" }, { 1, "Dave" }
    };
    

    使用接口声明对象实例意味着您将被强制仅使用该接口声明的方法,这可以使您以后更容易切换实现。当然,这不那么冗长:

    var players = new SortedList<int, string> { { 0, "John" }, { 1, "Dave" } };
    

    var的使用是一个有很多争论历史的话题。