【问题标题】:Clearing a List<string> removes all values from Dictionary List of Strings, C#清除 List<string> 从字典字符串列表中删除所有值,C#
【发布时间】:2015-11-24 10:29:19
【问题描述】:

尝试读取 csv 文件,并获取流中的第一个单词,将其放入字典中,同时将以下单词添加到该字典中的列表中。

但是,我发现(在调试过程中)当我决定在循环中清除列表时,它之前添加到字典中的所有值也会被清除。我想我错误地假设它复制了列表,它实际上只是引用了同一个列表?我应该在每次迭代时创建一个新列表吗?代码如下:

public class TestScript : MonoBehaviour {

// Use this for initialization
void Start() {

    Dictionary<string, List<string>> theDatabase = new Dictionary<string, List<string>>();
    string word;
    string delimStr = ",.:";
    char[] delimiter = delimStr.ToCharArray();
    List<string> theList = new List<string>();


    using (StreamReader reader = new StreamReader("testComma.csv")) {
        while (true) {
            //Begin reading lines
            string line = reader.ReadLine();
            if (line == null) {
                break;
            }
            //Begin splitting lines, adding to array.
            string[] split2 = line.Split(delimiter, StringSplitOptions.RemoveEmptyEntries);

            //Loop to hold the first word in the stream
            for(int i = 0; i <= 0; i++) {
                word = split2[i];

                //loop to hold the following words in to list.
                for (int y = 1; y < split2.Length; y++) {
                    theList.Add(split2[y]);
                }

                //Add word/list combo in to the database
                theDatabase.Add(word, theList);

                //clear the list.
                theList.Clear();
            }
        }
    }

    foreach (KeyValuePair<string, List<string>> pair in theDatabase) {
        string keys;
        List<string> values;

        keys = pair.Key;
        values = pair.Value;
        print(keys + " = " + values);

    }
  }
}

底部的 foreach 循环只是为了让我可以看到结果。此外,由于我是初学者,因此欢迎对本文的编写方式提出任何批评。

【问题讨论】:

  • 是的,您需要复制列表并将其添加到字典中,或者在外部循环的每次迭代中创建一个新列表

标签: c# string list dictionary streamreader


【解决方案1】:

是的,您正在向字典中添加相同的对象。

你可以改变:

theDatabase.Add(word, theList);

收件人:

theDatabase.Add(word, theList.ToList());

方法ToList() 对您的List&lt;T&gt; 进行浅拷贝

【讨论】:

  • 我尝试这样做时收到以下错误:CS1061 'List' 不包含 'ToList' 的定义,并且没有扩展方法 'ToList' 接受类型为 'List' 可以找到(您是否缺少 using 指令或程序集引用?)
  • 已修复。我没有提到 Linq,
【解决方案2】:

C# 是通过引用传递的。
所以,theList 和你的Dictionary 中的列表是同一个对象。

最简单的解决方案是停止清除您的List,而是每次都创建一个新的:

for(int i = 0; i <= 0; i++) {
    List<string> theList = new List<string>(); // it is in a loop now

    word = split2[i];

    //loop to hold the following words in to list.
    for (int y = 1; y < split2.Length; y++) {
        theList.Add(split2[y]);
    }

    //Add word/list combo in to the database
    theDatabase.Add(word, theList);

    //clear the list.
    //theList.Clear(); - not required anymore
}

更具可读性和清晰的解决方案:创建列表,插入项目,将列表粘贴到字典中,继续迭代。
由于没有 List 清除,它的性能也更高 - List&lt;T&gt;.Clear() 是线性运算,需要 O(n) 运算。

【讨论】:

  • 谢谢,我正在清除它,因为我想在没有旧条目的情况下重新使用它。
【解决方案3】:

是的,正如大家所说,列表是引用类型。您需要制作一份副本以避免.Clear() 清除所有列表。

你总是可以这样写你的代码:

void Start()
{
    string delimStr = ",.:";
    Dictionary<string, List<string>> theDatabase = 
        File
            .ReadAllLines("testComma.csv")
            .Select(line => line.Split(delimStr.ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
            .ToDictionary(x => x[0], x => x.Skip(1).ToList());

    /* foreach here */
}

}

列表引用没有问题。

【讨论】:

    猜你喜欢
    • 2021-09-23
    • 1970-01-01
    • 2014-09-14
    • 2018-09-10
    • 2020-07-14
    • 2019-04-07
    • 2020-04-05
    • 2017-03-16
    • 1970-01-01
    相关资源
    最近更新 更多