如何正确翻译“var” lambda 表达式的结果到具体类型?
所以我正在尝试了解有关 lambda 表达式的更多信息。我读了这个问题 在 stackoverflow 上,同意所选答案,并尝试使用 C# 中的控制台应用程序使用简单的 LINQ 表达式来实现该算法。
我的问题是:如何将 lambda 表达式的“var result”转换为可用的对象,然后可以打印结果?
我也希望能深入解释当我声明 outer =>; 时发生的情况。 external.Value.Frequency
(我已经阅读了大量 lambda 表达式的解释,但额外的说明会有所帮助)
C#
//Input : {5, 13, 6, 5, 13, 7, 8, 6, 5}
//Output : {5, 5, 5, 13, 13, 6, 6, 7, 8}
//The question is to arrange the numbers in the array in decreasing order of their frequency, preserving the order of their occurrence.
//If there is a tie, like in this example between 13 and 6, then the number occurring first in the input array would come first in the output array.
List<int> input = new List<int>();
input.Add(5);
input.Add(13);
input.Add(6);
input.Add(5);
input.Add(13);
input.Add(7);
input.Add(8);
input.Add(6);
input.Add(5);
Dictionary<int, FrequencyAndValue> dictionary = new Dictionary<int, FrequencyAndValue>();
foreach (int number in input)
{
if (!dictionary.ContainsKey(number))
{
dictionary.Add(number, new FrequencyAndValue(1, number) );
}
else
{
dictionary[number].Frequency++;
}
}
var result = dictionary.OrderByDescending(outer => outer.Value.Frequency);
// How to translate the result into something I can print??
有关打印命令的完整答案,请参阅 我的答案在这里。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
首先,“lambda 表达式”只是表达式中
a=>b
形式的部分。查询的其余部分只是一个以 lambda 作为参数的方法调用。无论如何,如果我可以教人们有关 LINQ 的一件事,那就是:“结果”不是查询的结果,而是查询本身。
如果您想查看结果,请询问每个结果的查询:
当然。我们首先确定所涉及的所有内容的类型。我们看到 lambda 是一个接受 KeyValuePair 并返回 int 的函数,因此我们生成一个方法
接下来我们采用该方法并从中创建一个委托:
并重写扩展方法调用:
并重写 var:
我希望你同意您输入的代码比这些混乱的代码更具可读性。类型推理很可靠。
结果是一个对象,表示按给定键对该字典进行排序的能力。仔细阅读:它代表按该键对字典进行排序的能力。在您询问结果之前,它实际上不会这样做;到目前为止,它只是一个对象,它表示“当要求结果时,按此键对字典进行排序”。
假设你要求一个结果。它如何计算排序列表?它向字典询问每个元素。然后它对每个元素调用 MyLambda,返回一个整数,因此我们现在有一对字典键值对和整数。然后,它构建一个按该整数排序的对列表。然后,根据您的要求,它一次分发一个列表中的元素。
啊,我看到了困惑 我在上面对语义分析进行的确切顺序
做了一些谎言,这是 C# 中更微妙和有趣的部分之一
;出于教学原因,
。 :
我们看到我们有可能调用这个方法:
但是我们不知道 T 和 K 是什么,所以我们首先查看不是 lambda 的所有内容。您的字典实现了
IEnumerable。 ;>
所以我们首先说“T 可能是KeyValuePair
”此时我们无法从 lambda 之外的内容中推断出任何其他内容,因此我们开始查看 lambda 表达式,我们看到有一个 lambda
o=>o.Value.Frequency
,到目前为止我们已经确定 keyExtractor 的类型为Func ;, K>
并且我们仍在寻找 K。所以我们说假设 lambda 实际上是:我们问它绑定吗?是的!是的,确实如此。我们可以成功地编译这个 lambda,没有错误,并且当我们这样做时,我们看到它的所有 return 语句都返回一个 int。
因此我们推断 K 是 int,现在我们对整个事情有了完整的类型分析。
这是一个相当简单的推论;他们可能会变得更奇怪。如果您对这个主题特别感兴趣,请参阅我博客上的“类型推断”档案。
http://blogs.msdn.com/ericlippert/archive/ Tags/Type+Inference/default.aspx
特别是,这是我解释上述内容以及其他一些有趣案例的视频:
http://blogs.msdn.com/ericlippert/archive/2006/11/17/ a-face-made-for-email-part- Three.aspx
First off, the "lambda expression" is only the portion of the expression that is of the form
a=>b
. The rest of your query is just a method call that takes a lambda as its argument.Anyway, if I could teach people one thing about LINQ it would be this: "result" isn't the results of the query, it is the query itself.
If you want to see the results, ask the query for each result:
Sure. We begin by working out the types of everything involved. We see that the lambda is a function which takes a KeyValuePair and returns an int, so we generate a method
Next we take that method and create a delegate out of it:
and rewrite the extension method call:
and rewrite the var:
I hope you agree that the code you typed in is a whole lot more readable than this mess. Type inference rocks.
The result is an object which represents the ability to sort this dictionary by the given key. Read that carefully: it represents the ability to sort the dictionary by that key. It does not actually do that until you ask for a result; so far, all it is is an object that says "when asked for a result, sort the dictionary by this key".
Suppose you ask for a result. How does it compute the sorted list? It asks the dictionary for each element. Then it calls MyLambda on each element, which gives back an integer, so we now have a pair of dictionary key-value pairs and integers. It then builds a list of pairs sorted on that integer. Then it hands out elements of that list one at a time, as you ask for them.
Ah, I see the confusion; for pedagogic reasons I fibbed a bit above regarding the exact order in which the semantic analysis proceeds.
How we do this type inference is one of the more subtle and interesting parts of C#.
Here's how it works.
We see that OrderByDescending is declared as:
and we see we have a potential call to this method:
But we do not know what T and K are. So we start by looking at everything that is NOT a lambda. Your dictionary implements
IEnumerable<KeyValuePair<int, FrequencyOrValue>>
so we start by saying "T is probablyKeyValuePair<int, FrequencyOrValue>
".At this point there is nothing else we can deduce from stuff that is not lambdas so we start looking at the lambdas. We see that we have a lambda
o=>o.Value.Frequency
and so far we have determined that the type of keyExtractor isFunc<KeyValuePair<int, FrequencyOrValue>, K>
and we are still looking for K. So we say suppose the lambda actually was:And we ask does it bind? YES! Yes it does. We can successfully compile this lambda without error and when we do so, we see that all of its return statements return an int.
Therefore we deduce that K is int, and we now have a full type analysis of the whole thing.
This is a fairly straightforward inference; they can get much weirder. See the "type inference" archive on my blog if this subject particularly interests you.
http://blogs.msdn.com/ericlippert/archive/tags/Type+Inference/default.aspx
In particular, here's a video of me explaining the stuff above plus a few other interesting cases:
http://blogs.msdn.com/ericlippert/archive/2006/11/17/a-face-made-for-email-part-three.aspx
OrderByDescending 函数将返回一个 IEnumerable,实际上是一个 IOrderedEnumerable,其中 TSource 是原始可枚举的类型源。
当您使用字典时,OrderByDescending 将返回一个:
对象,该对象将根据提供的表达式进行排序。
The OrderByDescending Function will return a IEnumerable, actually a IOrderedEnumerable where the TSource is the type source of the original enumerable.
As you are working with a Dictionary, the OrderByDescending will return a:
object, which will be ordered according to the expression provided.
此行为您提供一个名为 result 的
IOrderedEnumerable>
。至于 lambda,它的类型意味着它接受
KeyValuePair
参数(您将其称为外部),并返回与该对的值的Frequency 属性相对应的整数。因此,生成的 IOrderedEnumerable 按频率以相反的顺序排序。This line is giving you an
IOrderedEnumerable<KeyValuePair<int, FrequencyAndValue>>
called result. As for the lambda, it is of the typeWhich means it accepts a
KeyValuePair<int, FrequencyAndValue>
parameter (which you are calling outer), and returns an integer corresponding to the pair's value's Frequency property. So the resulting IOrderedEnumerable is being sorted by the frequency in a reverse order.为了获得完整的答案文档,我使用更通用的“item”以及更具体的 IOrderedEnumerable 打印了输出。
For the sake of full answer documentation, I printed the output using the more general "item" as well as the more specific IOrderedEnumerable.