【问题标题】:From string line to List<list> with split the same values从字符串行到 List<list> 拆分相同的值
【发布时间】:2016-04-09 01:23:28
【问题描述】:

我编写静态方法,从文本文件中读取科学数字(X,Y)并将其放入列表列表。但我不知道为什么文件中的下一个值会覆盖所有其他值。

IF != 100 - 100 是文本文件的第一个值,它是我的程序的唯一属性。

 static List<List<double>> DownloadData(string path1)
    {
        List<List<double>> lista = new List<List<double>>();
        List<double> doubelowa = new List<double>();
        doubelowa.Clear();
        string line = null;
        try
        {

            using (TextReader sr = File.OpenText(path1))
            {

                while ((line = sr.ReadLine()) != null)
                {
                    doubelowa.Clear();
                    if (line != "100")
                    {
                        var d = line.Split().Select(f => double.Parse(f, System.Globalization.NumberStyles.Float, CultureInfo.InvariantCulture));
                        doubelowa.AddRange(d);
                        lista.Add(doubelowa);
                    }
                }
            }
        }
        finally
        {

        }
        return lista;
    }

在我写这个方法之前,它的工作很棒。但是现在当我编写越来越多的代码时,我不知道发生了什么变化。我尝试修复它,但是...

它与当地人的屏幕: https://onedrive.live.com/redir?resid=DF3242C9A565ECD1!4549&authkey=!AEDu90t1iNQj4MY&v=3&ithint=photo%2cpng

由于某种原因,double.clear() 清除了列表 Lista 的值。为什么?

【问题讨论】:

标签: c# list


【解决方案1】:

那是因为你一遍又一遍地添加同一个对象。如果你想存储不同的Lists,你需要在每次迭代时使用一个新的List

if (line != "100")
{
   var d = line.Split().Select(f => double.Parse(f, System.Globalization.NumberStyles.Float, CultureInfo.InvariantCulture));
   lista.Add(new List<double>(d));
}

如果您添加doubelowa,您只是一遍又一遍地添加相同的引用(并且您在每次迭代时都会覆盖它)


使用截图编辑后

以防万一您不清楚答案...当您将doublelowa 添加到lista 时,您只是每次都添加相同的列表

所以lista 只是在每个元素上保持相同的对象:

  • lista[0] 指向doublelowa
  • lista[1] 指向 doublelowa
  • lista[2] 指向 doublelowa

因此,如果您在任何时候清除doublelowalista 的所有元素都将指向同一个空列表。正如我上面写的,解决方案是让每个元素成为一个不同列表,而不是doublelowa,这可以通过我编写的代码来实现(你可以完全忽略doublelowa,因为它不是不再需要了)。

【讨论】:

  • 没问题,只要你足够了解问题/解决方案(再次:它与垃圾收集无关,所以如果你理解,我可能需要进一步或更详细地解释它)
【解决方案2】:

我相信正在发生的事情是你只创建一个 List 对象,你让 lista 一遍又一遍地指向它。这样,通过改变 doubelowa 就会改变它们,因为它们实际上都是同一个对象。要更正此问题,请尝试将 doubelowa.Clear(); 替换为 doubelowa = new List&lt;double&gt;();

【讨论】:

  • 是的,我的回答可能不够漂亮? :-)
【解决方案3】:

Jcl 谢谢你的解释。我通过幸运的尝试来修复它,如下所示。但是没有你,我不认为引用是这样的。

这可能是因为引用是对每个单元格的引用,并且 while 循环已完成垃圾收集器没有清理?如果你愿意,请详细解释一下。

                if (line != "100")
                {
                    List<double> doubelowa = new List<double>();
                    doubelowa.AddRange(line.Split().Select(f => double.Parse(f, System.Globalization.NumberStyles.Float, CultureInfo.InvariantCulture)));
                    lista.Add(doubelowa);
                }

【讨论】:

  • 这正是我在回答中所写的。您正在每次迭代中创建一个新列表(您将其称为doublelowa,我只是没有为它创建一个变量,因为它不是必需的,但原理相同)。这与垃圾收集器无关。如果您有任何不明白的地方,请不要犹豫,我会尝试更详细地解释
  • 我在这个循环中牵连了 GC,因为当引用从这个列表中消失并且只保持清晰的值时,我开始思考。我的问题是。当我在其单元格中返回“lista”时,只有明确的价值?当引用不同并且只保留值时?
  • 只要您的列表被任何其他对象使用,或者在范围内的变量中,它们就不会被 GC。您添加到lista 的列表由lista 使用,并且函数返回的变量(即lista 指向的对象)将在调用者的范围内,只要您使用它(如果在那里分配给一个变量,它可能会更长的使用时间)。一旦你不再使用那个对象,它最终会被 GCed
【解决方案4】:

你也可以在分割线后通过IEnumerator的ToList方法创建新的列表。 使用 Linq 方法简洁代码。 列表> r=File.ReadAllLines(fileName).SkipWhile((line) => line=="100") .选择((线){ line.Split().Select(f => double.Parse(f, System.Globalization.NumberStyles.Float, CultureInfo.InvariantCulture)).ToList()).ToList();

【讨论】:

  • 谢谢我尝试其他方法!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多