我喜欢C#,我喜欢这个框架,我也喜欢尽可能多地学习。今天我开始在C#中阅读有关LINQ的文章,我找不到任何对他以前从未使用SQL的初学者有用的东西。
我发现this文章非常有用,我理解它的一小部分内容,但我想了解更多示例。
在阅读了几次之后,我尝试在我的函数中使用LINQ,但是我失败了。
private void Filter(string filename)
{
using (TextWriter writer = File.CreateText(Application.StartupPath + "\\temp\\test.txt"))
{
using(TextReader reader = File.OpenText(filename))
{
string line;
while((line = reader.ReadLine()) != null)
{
string[] items = line.Split('\t');
int myInteger = int.Parse(items[1]);
if (myInteger == 24809) writer.WriteLine(line);
}
}
}
}
这就是我所做的,但没有奏效,结果总是错误的。
private void Filter(string filename)
{
using (TextWriter writer = File.CreateText(Application.StartupPath + "\\temp\\test.txt"))
{
using(TextReader reader = File.OpenText(filename))
{
string line;
while((line = reader.ReadLine()) != null)
{
string[] items = line.Split('\t');
var Linqi = from item in items
where int.Parse(items[1]) == 24809
select true;
if (Linqi == true) writer.WriteLine(line);
}
}
}
}
我要求两件事:
提前谢谢!
答案 0 :(得分:19)
有一件事可以使你的样本更“LINQy”是一个IEnumerable<string>
用于从文件中读取行。以下是来自MiscUtil的LineReader
课程的简化版本:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
public sealed class LineReader : IEnumerable<string>
{
readonly Func<TextReader> dataSource;
public LineReader(string filename)
: this(() => File.OpenText(filename))
{
}
public LineReader(Func<TextReader> dataSource)
{
this.dataSource = dataSource;
}
public IEnumerator<string> GetEnumerator()
{
using (TextReader reader = dataSource())
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
现在你可以使用它:
var query = from line in new LineReader(filename)
let items = line.Split('\t')
let myInteger int.Parse(items[1]);
where myInteger == 24809
select line;
using (TextWriter writer = File.CreateText(Application.StartupPath
+ "\\temp\\test.txt"))
{
foreach (string line in query)
{
writer.WriteLine(line);
}
}
请注意,没有let
子句可能会更有效:
var query = from line in new LineReader(filename)
where int.Parse(line.Split('\t')[1]) == 24809
select line;
此时你可以用“点符号”合理地完成所有操作:
var query = new LineReader(filename)
.Where(line => int.Parse(line.Split('\t')[1]) == 24809);
但是,我更喜欢原始查询的可读性:)
答案 1 :(得分:6)
101 LINQ Samples肯定是一个很好的例子集合。同样LINQPad可能是玩LINQ的好方法。
答案 2 :(得分:5)
以网站为起点,您可以尝试Hooked on LINQ
修改:
原始网站现在似乎已经死亡(域名出售)。
以下是上一版本的互联网档案:https://web.archive.org/web/20140823041217/http://www.hookedonlinq.com/
答案 3 :(得分:3)
如果你正在读书,我发现LINQ in action Manning Publications是一个很好的起点。
答案 4 :(得分:1)
答案 5 :(得分:1)
我开始时从以下网站中获得了很多:
http://msdn.microsoft.com/en-us/library/bb425822.aspx
http://weblogs.asp.net/scottgu/archive/2007/05/19/using-linq-to-sql-part-1.aspx
答案 6 :(得分:1)
首先,我将介绍这种方法:
private IEnumerable<string> ReadLines(StreamReader reader)
{
while(!reader.EndOfStream)
{
yield return reader.ReadLine();
}
}
然后,我会重构使用它的主要方法。我将两个using
语句放在同一个块之上,并添加了范围检查以确保items[1]
不会失败:
private void Filter(string fileName)
{
using(var writer = File.CreateText(Application.StartupPath + "\\temp\\test.txt"))
using(var reader = File.OpenText(filename))
{
var myIntegers =
from line in ReadLines(reader)
let items = line.Split('\t')
where items.Length > 1
let myInteger = Int32.Parse(items[1])
where myInteger == 24809
select myInteger;
foreach(var myInteger in myIntegers)
{
writer.WriteLine(myInteger);
}
}
}
答案 7 :(得分:1)
对于Linq书籍,我建议:
http://www.ebookpdf.net/screen/cover2/51n4fa2xxvl_083.jpg http://www.diesel-ebooks.com/mas_assets/full/0321564189.jpg
两本都是出色的书籍,详细介绍了Linq。
要为as-much-linq-as-possible主题添加另一个变体,这是我的看法:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace LinqDemo
{
class Program
{
static void Main()
{
var baseDir = AppDomain.CurrentDomain.BaseDirectory;
File.WriteAllLines(
Path.Combine(baseDir, "out.txt"),
File.ReadAllLines(Path.Combine(baseDir, "in.txt"))
.Select(line => new KeyValuePair<string, string[]>(line, line.Split(','))) // split each line into columns, also carry the original line forward
.Where(info => info.Value.Length > 1) // filter out lines that don't have 2nd column
.Select(info => new KeyValuePair<string, int>(info.Key, int.Parse(info.Value[1]))) // convert 2nd column to int, still carrying the original line forward
.Where(info => info.Value == 24809) // apply the filtering criteria
.Select(info => info.Key) // restore original lines
.ToArray());
}
}
}
请注意,我将制表符分隔列更改为以逗号分隔的列(在我的编辑器中更容易将制表符转换为空格;-))。对输入文件运行此程序时:
A1,2
B,24809,C
C
E
G,24809
输出将是:
B,24809,C
G,24809
你可以通过用Jon Skeet的LineReader替换“File.ReadAllLines”和“File.WriteAllLines”来改善这个解决方案的内存需求(和类似的LineWriter一样,采用IEnumerable并将每个返回的项目作为一个新的输出文件写入线)。这将改变上面的解决方案“将所有行作为数组放入内存,过滤掉它们,在内存中创建另一个数组以获得结果并将此结果写入输出文件”以“逐个”读取输入文件中的行,如果是这样的话line符合我们的标准,立即将其写入输出文件“(管道方法)。
答案 8 :(得分:1)
我发现这篇文章对于理解LINQ非常重要,LINQ基于.NET 3.0中引入的许多新结构。 3.5:
我会警告你,这是一个很长的阅读,但如果你真的想了解Linq是什么,我相信它是必不可少的
http://blogs.msdn.com/ericwhite/pages/FP-Tutorial.aspx
快乐阅读
答案 9 :(得分:0)
如果我在可能的情况下使用LINQ重写过滤函数,它看起来像这样:
private void Filter(string filename)
{
using (TextWriter writer = File.CreateText(Application.StartupPath + "\\temp\\test.txt"))
{
var lines = File.ReadAllLines(filename);
var matches = from line in lines
let items = line.Split('\t')
let myInteger = int.Parse(items[1]);
where myInteger == 24809
select line;
foreach (var match in matches)
{
writer.WriteLine(line)
}
}
}
答案 10 :(得分:0)
回答第一个问题,坦率地说,除了作为练习外,没有太多理由以上述功能的方式使用LINQ。事实上,它可能只是让函数更难阅读。
LINQ在集合上运行比单个元素更有用,我会以这种方式使用它。所以,这是我尝试在函数中使用尽可能多的LINQ (没有提到效率,我不建议将整个文件读入内存,就像这样) :
private void Filter(string filename)
{
using (TextWriter writer = File.CreateText(Application.StartupPath + "\\temp\\test.txt"))
{
using(TextReader reader = File.OpenText(filename))
{
List<string> lines;
string line;
while((line = reader.ReadLine()) != null)
lines.Add(line);
var query = from l in lines
let splitLine = l.Split('\t')
where int.Parse(splitLine.Skip(1).First()) == 24809
select l;
foreach(var l in query)
writer.WriteLine(l);
}
}
}
答案 11 :(得分:-1)
不能只检查Linqi是否属实...... Linqi是IEnumerable<bool>
(在这种情况下)所以必须检查Linqi.First() == true
这是一个小例子:
string[] items = { "12121", "2222", "24809", "23445", "24809" };
var Linqi = from item in items
where Convert.ToInt32(item) == 24809
select true;
if (Linqi.First() == true) Console.WriteLine("Got a true");
您也可以迭代Linqi,在我的例子中,该集合中有2个项目。