Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用LINQ从文件中选择字符串,将其拆分并返回指定的成员_C#_.net_Linq_File Io_Lambda - Fatal编程技术网

C# 使用LINQ从文件中选择字符串,将其拆分并返回指定的成员

C# 使用LINQ从文件中选择字符串,将其拆分并返回指定的成员,c#,.net,linq,file-io,lambda,C#,.net,Linq,File Io,Lambda,我有一个非常大的文件(>1GB),它是管道分隔的。 我想使用file.readlines查询文件,拆分每一行,根据索引列表(我将提供索引数组)从拆分的行中选择特定元素,并将其返回到自定义类型类对象的字典中 目前我有: strIndexes = "1,3,5,7"; var selected = strIndexes.Split(',') .Select(x => int.Parse(x))

我有一个非常大的文件(>1GB),它是管道分隔的。 我想使用file.readlines查询文件,拆分每一行,根据索引列表(我将提供索引数组)从拆分的行中选择特定元素,并将其返回到自定义类型类对象的字典中

目前我有:

strIndexes = "1,3,5,7";
var selected = strIndexes.Split(',')
                         .Select(x => int.Parse(x))
                         .Select(index => File.readlines(myFile)
                         .Select(x => split('|')[index]).toArray();
但是,此查询由索引引导,效率不高。 它返回4个向量,每个向量对应上面示例中指定的4个索引

我将感谢任何帮助

更新:

谢谢大家的评论。 我正在添加一些示例数据。 文件数据如下所示:

Line1: aa|ab|de|gt|hj|de|fr|gt|hy // Header
Line2: sd|12|f4|tr|hj|df|ds|e3|12
Line3: 34|fd|3d|35|df|45|dq|32|dd
.
.
.
Line N 34|df|f3|df|33|s2|23|df|44
N=数百万行。 数据格式仅用于示例,每个单元格包含不同长度和结构的字符串

现在,用户以标题列名的形式输入所需的数据,例如:ab、de、fr、hy,我解析它并理解我需要第2、3、7和9列。 现在我想解析该文件并返回一个对象,其中每个条目都是一个字典条目,它表示一行中的一个数据,其中包含一个键(它是数据列之一)和一个值,该值是标记化数据的字符串[]

让我们假设在这个例子中,我希望数据按第7列排序,所以最后的dict是:

[ds]->[12,f4,12]
[dq]->[fd,3d,dd]
.
.
.
[23]->[df,f3,44]

我建议您编写自己的标记器(或查找标记器),您可以使用并搜索“|”或“,”,构建自己的状态机来告诉它将这些值放在何处。

有些猜测,但可能这就是您想要做的:

// Split indexes string to integers
var indexes = strIndexes.Split(',').Select(int.Parse);

// Read file once
var lines = File.ReadLines(myFile);

// Split them (thank you, devundef!)
var splitLines = lines.Select(line => line.Split('|')).ToArray();

// Create dictionary index => column array
var dict = indexes.ToDictionary(
        index => index,
        index => splitLines.Select(splitLine => splitLine[index]).ToArray()
    );

首先,在查询外部解析索引字符串(strIndex),以避免多次重复该步骤:

string strIndexes = "7,2,3,9";
int[] indexes = Array.ConvertAll(strIndexes.Split(','), e => int.Parse(e) - 1);
请注意,我将7放在第一位,因为假设第一个索引是您的键索引可以简化所需的代码。我还注意到,您的索引在字符串中似乎是基于1的,这就是为什么我减去1来创建一个基于0的索引数组。然后,这将生成一个符合您请求的格式的
字典

var selected = (from line in File.ReadLines(myFile)
                let lineArray = line.Split('|')
                select (from index in indexes
                select lineArray[index]))
               .ToDictionary(key => key.First(), value => value.Skip(1).ToArray());
针对您的4行样本数据运行此操作将产生:

[fr]->[ab, de, hy]
[ds]->[12, f4, 12]
[dq]->[fd, 3d, dd]
[23]->[df, f3, 44]
根据该代码:

foreach (var item in selected)
{
    Console.WriteLine("[{0}]->[{1}]", item.Key, string.Join(", ", item.Value));
}

虽然您要求使用linq解决方案,但我认为这可能不是一个好的做法,因为您的文件很大,并且您会为单个任务分配大量内存,甚至会出现OutOfMemoryException

您只需分析文件的每一行,并提取每个索引的值:

public Dictionary<int, List<String>> ParseFile(String fileName, int[] indexes)
    var file = File.OpenText(myFile);
    var dict = indexes.ToDictionary(i => i, i => new List<string>());

    while(!file.EndOfStream)
    {
        var line = file.ReadLine().Split('|');
        foreach(var entry in dict)
            entry.Value.Add(line[entry.Key]);
    }
    file.Dispose();
    return dict;
}
公共字典解析文件(字符串文件名,int[]索引)
var file=file.OpenText(myFile);
var dict=index.ToDictionary(i=>i,i=>newlist());
而(!file.EndOfStream)
{
var line=file.ReadLine().Split(“|”);
foreach(dict中的var条目)
entry.Value.Add(第[entry.Key]行);
}
Dispose();
返回命令;
}

首先,我会避免每次为每个索引读取文件。很难遵循您试图实现的目标。如果您可以提供示例输入和所需的输出,那么帮助您会容易得多。@Xander:我正确地将
读取行
.ToArray()
大小写为大小写,并将
.ToArray()
调用移到下一行以匹配语句的其余部分。什么在语义上发生了变化?@Lee我认为OP的问题正是——他希望避免重读文件,并寻找一种更有效的方法。指定技术来解决任意问题,而不是要求最好的技术来解决问题,就像要求烤箱以最有效的方式冷却啤酒一样。有可以进行多种优化:使用
File.ReadLines
进行外部拆分。我的想法是:
var lines=File.ReadLines(myFile)。选择(line=>line.split(“|”).ToArray(),因此只需枚举一次行,并使用一半的内存。很抱歉,我对你的答案嗤之以鼻:)ReadLines返回一个数组。。。不幸的是,没有要保存的内存。。。哦,它没有,把它和ReadAllLines混淆了!