请教一个简单的linq查询

wldt12345 2012-08-01 11:30:28
这是前几天一位csdn的童鞋提出的问题,我用查询表达是语法做出来了。现在想请教下,用方法语法拉姆达表达式该怎么写。
List<int> numbers = new List<int>() { 1, 2, 3 };
List<string> words = new List<string>() { "one", "two", "three" };
List<string> romanNumberals = new List<string> { "I", "II", "III" };

var test = from n in numbers
let numIndex = numbers.IndexOf(n)
from w in words
let wordIndex = words.IndexOf(w)
from r in romanNumberals
let rIndex = romanNumberals.IndexOf(r)
where numIndex == wordIndex && wordIndex == rIndex
select new { Arabic = n, Word = w, Roman = r };

foreach (var item in test)
{
Console.WriteLine("{0},{1},{2}", item.Arabic, item.Word, item.Roman);
}
输出结果:
1,one,I
2,two,II
3,three,III
...全文
201 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
threenewbee 2012-08-01
  • 打赏
  • 举报
回复
还有,VB、C#和F#的LINQ查询表达式略有不同。有可能一个C#查询表达式无法用VB写出来。
而其他托管语言,比如Delphi.NET则根本不支持LINQ表达式。

换一句话说,LINQ表达式是语言的特性,而不是.NET框架的特性。

遇到这种情况,你不得不使用LINQ操作符。当你缺乏思路的时候,也可以像我在3L那样,先写出LINQ表达式,再手工展开成LINQ操作符的形式。
threenewbee 2012-08-01
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]
引用 2 楼 的回复:

你是要功能等价,还是完全等价。

如果是后者,写起来很复杂,如果是前者

var query = numbers.Zip(words, (x, y) => new { x, y }).Zip(romanNumberals, (x, y) => new { Arabic = x.x, Word = x.y, Roman = y });

非常感谢,功能等价就……
[/Quote]

用selectmanay也不必写得那么复杂,我只是1:1复制你的linq表达式。你看出每个let都会使得投影的操作变深一层,人写是没有必要的。
你的选择B 2012-08-01
  • 打赏
  • 举报
回复
var result = numbers.Select(c => new { c, m = words.SingleOrDefault(n => words.IndexOf(n) == numbers.IndexOf(c)), p = romanNumberals.SingleOrDefault(q => romanNumberals.IndexOf(q) == numbers.IndexOf(c)) });
foreach(var v in result)
{
int s1 = v.c;
string s2 = v.m;
string s3 = v.p;
}
threenewbee 2012-08-01
  • 打赏
  • 举报
回复
首先我说了,Linq表达式只是Linq操作符写法的一个子集,所以Linq表达式的一个缺点就是,它不能完全实现所有的Linq功能。除此之外,我的原则是,哪种方式简洁,你就用哪种方法。显然,两个Zip比你的写法简单,之所以你的写法复杂,就是因为Linq表达式不能直接支持zip操作,你必须用更多的操作去模拟。
特别地,Linq表达式很适合写诸如分组和连接的操作,因为更优雅。你很难用Linq操作符表明这种层次关系。

Linq操作符和Linq表达式可以混合使用,比如
var query = from x in data.select(x => x.age)
group x by x / 10 into g
select g.Count();
或者
var query = (from x in data
group x by x.age / 10 into g
select g).Select(x => x.Count());
wldt12345 2012-08-01
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]

引用 6 楼 的回复:

记住,所有的LINQ表达式都可以用LINQ操作符实现。LINQ表达式只是语法糖。具体你可以看我4L的两个回答。我解释了let join和多重选择(笛卡尔积)的LINQ操作符写法,至于group,也很简单:
var query = from a in data
group a by a into g
select g;
等效
var que……

好的……
[/Quote]
三楼貌似也是你。。。。。
sorry,没看仔细。。。。
wldt12345 2012-08-01
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]

记住,所有的LINQ表达式都可以用LINQ操作符实现。LINQ表达式只是语法糖。具体你可以看我4L的两个回答。我解释了let join和多重选择(笛卡尔积)的LINQ操作符写法,至于group,也很简单:
var query = from a in data
group a by a into g
select g;
等效
var que……
[/Quote]
好的,非常感谢,我会好好看。
wldt12345 2012-08-01
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

你是要功能等价,还是完全等价。

如果是后者,写起来很复杂,如果是前者

var query = numbers.Zip(words, (x, y) => new { x, y }).Zip(romanNumberals, (x, y) => new { Arabic = x.x, Word = x.y, Roman = y });
[/Quote]
非常感谢,功能等价就可以了。各位大神的思路真是开阔,一楼用的类似表驱动的方法,你又能想到用zip(),这些方法我都想不到。
我用查询表达式from 嵌套from做出来的,一想对应的语法和SelectMany接近,就用SelectMany做,结果越写越晕,写到最后就和3楼那位大神一样了,不过他比我强,最起码写到最后写出来了。。。。

说到这里,我想请教一个问题,查询表达式语法和拉姆达方法语法有优劣之分吗?在平时工作中使用是不是也要视具体情况而定,有时适合用查询表达式,有时适合用拉姆达?
threenewbee 2012-08-01
  • 打赏
  • 举报
回复
记住,所有的LINQ表达式都可以用LINQ操作符实现。LINQ表达式只是语法糖。具体你可以看我4L的两个回答。我解释了let join和多重选择(笛卡尔积)的LINQ操作符写法,至于group,也很简单:
var query = from a in data
group a by a into g
select g;
等效
var query = data.GroupBy(a => a).Select(g => g);

至于GroupBy,Join和什么延迟查询没有关系。
wldt12345 2012-08-01
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

C# code

List<int> numbers = new List<int>() { 1, 2, 3 };
List<string> words = new List<string>() { "one", "two", "three" };
List<string> romanNumberals = new Lis……
[/Quote]
大神好速度,谢谢了。
另外想请教下,一般查询表达式语法都会有一个与他相对应的拉姆达方法语法,比如
var query = from w in words
select w;
对应
var query = words.Select(w=>w);

var query = from w in words
where w.StartWith("S")
select w;
中的where子句对应
var query = words.Where(w=>w.StartWith("S"));
比较复杂一点的延迟查询GroupBy,Join也都有相应的表达式语法对应。

但是现在一直搞不清,查询表达式语法中的let字句对应的拉姆达方法语法是什么,是要视具体情况而定吗?
还有拉姆达语法的.SelectMany(),是不是对应的就是查询语法就是多个 from 嵌套。
threenewbee 2012-08-01
  • 打赏
  • 举报
回复
不过你可以参考我这两个回答:

http://topic.csdn.net/u/20120412/15/b36be23a-c01e-49b3-a011-3ca1b2acc68b.html
http://topic.csdn.net/u/20120718/10/50bf4829-f65d-404e-ba53-fbbd7932e7c1.html
threenewbee 2012-08-01
  • 打赏
  • 举报
回复
这是完全等效的写法

var test = numbers.SelectMany(n => words.SelectMany(w => romanNumberals.Select(r => new { n, w, r }).Select(x => new { x, rIndex = romanNumberals.IndexOf(x.r) })).Select(x => new { x, wordIndex = words.IndexOf(x.x.w) })).Select(x => new { x, numIndex = numbers.IndexOf(x.x.x.n) }).Where(x => x.numIndex == x.x.wordIndex && x.x.wordIndex == x.x.x.rIndex).Select(x => new { Arabic = x.x.x.x.n, Word = x.x.x.x.w, Roman = x.x.x.x.r });

我想我写着晕,你看着更晕了。
threenewbee 2012-08-01
  • 打赏
  • 举报
回复
你是要功能等价,还是完全等价。

如果是后者,写起来很复杂,如果是前者

var query = numbers.Zip(words, (x, y) => new { x, y }).Zip(romanNumberals, (x, y) => new { Arabic = x.x, Word = x.y, Roman = y });
bdmh 2012-08-01
  • 打赏
  • 举报
回复

List<int> numbers = new List<int>() { 1, 2, 3 };
List<string> words = new List<string>() { "one", "two", "three" };
List<string> romanNumberals = new List<string> { "I", "II", "III" };
var vs = numbers.Select((v, index) => new { v, w = words[index], r = romanNumberals[index] });
foreach (var v in vs)
{
MessageBox.Show(v.v.ToString() + ":" + v.w + ":" + v.r);
}
wldt12345 2012-08-01
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]

var result = numbers.Select(c => new { c, m = words.SingleOrDefault(n => words.IndexOf(n) == numbers.IndexOf(c)), p = romanNumberals.SingleOrDefault(q => romanNumberals.IndexOf(q) == numbers.IndexOf(……
[/Quote]
3 q very much.
wldt12345 2012-08-01
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 的回复:]

还有,VB、C#和F#的LINQ查询表达式略有不同。有可能一个C#查询表达式无法用VB写出来。
而其他托管语言,比如Delphi.NET则根本不支持LINQ表达式。

换一句话说,LINQ表达式是语言的特性,而不是.NET框架的特性。

遇到这种情况,你不得不使用LINQ操作符。当你缺乏思路的时候,也可以像我在3L那样,先写出LINQ表达式,再手工展开成LINQ操作符的形式。
[/Quote]
好的,非常感谢,这是我第一次在csdn发帖提问,谢谢你耐心指教。
能加联系方式吗,以后有问题好请教你。平时我公司的事也比较多,不会耽误你太多时间。

8,497

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 LINQ
社区管理员
  • LINQ
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧