清除列表 <string> 从字符串字典列表中删除所有值,C#
Clearing a List<string> removes all values from Dictionary List of Strings, C#
尝试读取一个 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 循环只是为了让我可以看到结果。另外,由于我是初学者,欢迎对本文的编写方式提出任何批评。
是的,您正在向字典中添加相同的对象。
您可以更改:
theDatabase.Add(word, theList);
收件人:
theDatabase.Add(word, theList.ToList());
方法 ToList()
浅拷贝你的 List<T>
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<T>.Clear()
是线性运算,需要 O(n)
操作。
是的,正如大家所说,列表是引用类型。您需要复制一份以避免 .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 */
}
}
列表引用没有问题。
尝试读取一个 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 循环只是为了让我可以看到结果。另外,由于我是初学者,欢迎对本文的编写方式提出任何批评。
是的,您正在向字典中添加相同的对象。
您可以更改:
theDatabase.Add(word, theList);
收件人:
theDatabase.Add(word, theList.ToList());
方法 ToList()
浅拷贝你的 List<T>
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<T>.Clear()
是线性运算,需要 O(n)
操作。
是的,正如大家所说,列表是引用类型。您需要复制一份以避免 .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 */
}
}
列表引用没有问题。