【问题标题】:Splitting an array into multiple arrays将一个数组拆分为多个数组
【发布时间】:2014-07-16 08:59:35
【问题描述】:

我有一个文本文件,内容如下:

01 Dir1
abcd
efg
hij
klm
nop
qrs
tuv
wxy
zab
yxw
vut
dcb

02 Dir2
abcd
efg
hij
klm
nop
qrs
tuv
wxy
zab
yxw
vut
dcb

我得到一个通过读取文件创建的数组:

string[] lines = File.ReadAllLines(path);

这给了我一个包含所有条目的数组,包括空条目。

文本文件背后的想法是有一个文件夹和该文件夹中的文件在它后面。因此,“01 Dir1”是一个文件夹,之后的每一行直到一个空行都是一个文件。

我正在尝试的是有一个数组列表,因此从上面的示例中,列表中将有两个数组,一个从“01 Dir1”开始到空条目,下一个从“02 Dir2”到结束。

我可以遍历初始数组并为每个单独的目录创建列表,但是还有其他方法吗?

这种方法的问题在于,它最终会在内存中的不同集合中拥有相同的数据,一个来自 ReadAllLines 数组,另一个来自它的 subs。

【问题讨论】:

  • 你不能只在空间上分割吗?
  • The problem with that approach is that it will end up having the same data in different sets in memory, one from the ReadAllLines array and other the subs from it.... 为什么这是个问题?当对象超出范围时,垃圾收集器将获取您不再需要的对象。
  • 但是如果你不希望 ReadAllLines 的结果在单个数组中,那么不要使用它。还有其他读取文本文件的方法,您可以自定义文件的读取方式。
  • @psubsee2003 在这里不能依赖 GC。如果条目更多怎么办。您的第二条评论没有帮助。
  • @psubsee2003 问题不仅仅是一个对象被 GCed。数组需要连续的内存块,很容易导致内存不足的异常。

标签: c# file-io arraylist


【解决方案1】:

你想要下面这样的东西吗?

这将逐行读取,您可以决定如何处理它。 所以你不会得到一个包含所有条目的大字符串数组。 这里的结果将是一个包含字符串数组并跳过空行的列表。

//This will be the resulting list of arrays
var fileArrayList = new List<string[]>();
var filereader = new System.IO.StreamReader("yourfile");
var tmpArr = new List<string>();
var line = "";
while((line = filereader.ReadLine()) != null)
{
   if(String.IsNullOrEmpty(line){
       //put this array to our list
       fileArrayList.Add(tmpArr.ToArray());
       //clean the temp one
       tmpArr.Clear();
   }else
   {
       tmpArr.Add(line);
   }
}
//add the last entry
fileArrayList.Add(tmpArr.ToArray());
tmpArr = null;
//close the stream
filereader.Close();

【讨论】:

    【解决方案2】:

    这样您就可以拥有一个Dictionary,其中包含作为键的目录名和作为值的文件名的List&lt;string&gt;s。

    我没有处理特殊情况

    Dictionary<string, List<string>> data = new Dictionary<string,List<string>>();
    using (StreamReader reader = File.OpenText(filename))
    {
        while (!reader.EndOfStream)
        {
            string dirName = reader.ReadLine();
            List<string> currentFiles = new List<string>();
            data.Add(dirName, currentFiles);
            string fileName;
            while (!reader.EndOfStream && (fileName = reader.ReadLine()).Trim() != "")
            {
                currentFiles.Add(fileName);
            }
        }
    }
    

    【讨论】:

    • 这将有助于进一步使用字典。感谢感谢您的时间。
    【解决方案3】:
    list<string> listBeforeEmpty = new list<string>();
    list<string> listAfterEmpty = new list<string>();
    
    //Indicates whether the loop is before the empty line or not
    bool isEmptyLineFound = false;
    
     for (int i = 0; i < lines.Length; i++)
        {
    
         //If the empty line was found
         if (lines[i].CompareTo(@"") == 0)
                {
                    isEmptyLineFound = true;
                }
    
        //Add the line to the right list
         if (isEmptyLineFound == false) 
              listBeforeEmpty .Add(lines[i]);
         else listAfterEmpty .Add(lines[i]);
    
        }
    

    【讨论】:

      【解决方案4】:

      我决定试试看这个。这是我想出的,它应该可以工作:

          private static string[] _arr = new string[] // The stuff you read from file.
      
          private static List<string[]> _arrays = new List<string[]>(); 
      
              while (_arr.Length > 0)
              {
                  var a = _arr.TakeWhile(s =>
                  {
                      var li = _arr.ToList();
                      return 
                          s != string.Empty // Take it if the string isn't empty.
                          || (s == string.Empty && li.IndexOf(s) == 0) // Or if it's empty, but it's the first element in the array (it's the next one after we've just finished a batch)
                          || li.IndexOf(s) == _arr.Length; // And take it if it's the last element (in the case of an empty string as the last element)
                  }).ToArray();
      
                  _arrays.Add(a);
      
                  // Re-create the array to only include the stuff we haven't solved yet.
                  var l = _arr.ToList();
                  l.RemoveRange(0, a.Length);
                  _arr = l.ToArray();
              }
      

      它有点老套,可以改进,但它应该是你可以使用的。

      附带说明,您可能应该使用另一种方式来读取文件并在读取文件时确定这些单独的数组。它更高效,也可能更容易。

      【讨论】:

      • 不想回答就不要回答。将半生不熟的想法作为答案也无济于事。
      • @Codehelp 你说得对,我编辑了那部分。我确实想回答,因为这是一个有趣的问题。
      猜你喜欢
      • 1970-01-01
      • 2016-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多