我正在查看来自 Token Replacement and Identification 的解决方案:
string result = Regex.Replace(
text,
@"\[%RC:(\d+)%\]",
match => dict[int.Parse(match.Groups[1].Value)]);
而且我不明白 MatchEvaluator 是如何重载的。
我理解一些 lambda 表达式。它接受输入 match 然后从字典中查找一个整数?
但是 match 的值从何而来? match => dict[int.Parse(match.Groups[1].Value)]); 返回的值去哪里了?
编辑:你们中的一些人提到了Delegate。令人惊讶的是,在大学学习 CS 三年后,我还没有遇到过这个词。 Delegate 是什么,它在这种特定情况下做什么?
最后编辑:
我尝试使用以下代码编写自己的委托(delegate)
我的 token 采用 [@someTokenName]
public void CreateScript(Dictionary<string,string> dictionary, string path)
{
//used in the regex to identify the string to replace
var pattern = @"\[@[0-9a-fA-F]+\]";
//read in the file found at the path
var lines = File.ReadAllLines(path);
int lineCounter = 0;
foreach (string line in lines)
{
line = Regex.Replace(line, pattern, match => dictionary.TryGetValue((match.Groups[0].Value)));
}
但我一直收到“无法将 lambda 表达式转换为类型‘int’,因为它不是委托(delegate)类型”。我写的那行和解决方案中找到的那行有什么区别?
最佳答案
这是一个与 lambda 匹配的正则表达式,因此比您的常规旧 lambda 复杂一点。我们开始吧:
给定:
String result = Regex.Replace(
text,
@"\[%RC:(\d+)%\]",
match => dict[int.Parse(match.Groups[1].Value)]);
(1) text - 我们正在搜索的文本。
(2) @"\[%RC:(\d+)%\]" - 表示找到任何看起来像 "[%RC:{number}%]"的东西,其中 {number} 显然是一些数字(因为 \d 表示“一个数字”,而 \d+ 表示“一个或多个连续的数字”)。另请注意,{number} 或 \d+ 被 ( ) 包围,如 (\d+) 中一样。这一点很重要,因为这意味着该数字是一个“组”,这与我们下面的解释有关。组是一种从正则表达式中提取“有用”部分的方法。也就是说,我们不需要整个匹配,只需要数字值。
(3) 当它找到一个匹配时,它执行这个:match => dict[int.Parse(match.Groups[1].Value)]);
让我们从这部分开始:match => ...,它实际上与以下部分相同:
public String MatchEval(Match match)
{
}
请记住,lambda 表达式本质上只是常规函数的简写形式(除了编译器推断 match 的类型并且它的返回类型基于它所代表的委托(delegate) - 这里是 < strong="">MatchEvaluator - 稍后会详细介绍)。此处,输入 match 作为输入传递到 lambda 表达式中。然后你有 => 开始函数体类似于我们在上面的 MatchEval 函数中看到的 { }。因此,每次找到匹配项时,都会运行与此 block 等效的代码:
public String MatchEval(Match match)
{
// Here we grab the value from group (1) (the number in parentasis from our Regex)
return dict[int.Parse(match.Groups[1].Value)];
}
简而言之,请记住 lambda 只是函数的简写符号。如果您查看 Regex.Replace 的文档,您会看到 lambda 代表 MatchEvaluator定义为:
public delegate string MatchEvaluator(Match match);
这与我们上面的功能扩展一致。事实上,你可以简单地写:
String result = Regex.Replace(
text,
@"\[%RC:(\d+)%\]",
MatchEval);
(假设 dict 可以从一个单独的方法访问)并且该函数将以同样的方式工作,证明 lambda 只是完整函数的一个较短的表示法。
编辑: 至于你问题的第二部分,“什么是委托(delegate)”,委托(delegate)本质上解决了这个问题:“我不知道我想使用什么功能,但我知道它有什么签名”。考虑:
// This allows us to point to a math function with this signature,
// namely, takes two Int32 inputs, and returns an Int32.
public static delegate Int32 MathDelegate(Int32 lhs, Int32 rhs);
public static Int32 Add(Int32 lhs, Int32 rhs)
{
return lhs + rhs;
}
// Note the variable names aren't important, just their TYPE
public static Int32 Subtract(Int32 a, Int32 b)
{
return a - b;
}
static void Main()
{
// We can use a delegate to point to a "real" function
MathDelegate mathPerformer = Add;
Console.WriteLine(mathPerformer(2, 3)); // Output : 5
// Now let's point to "Subtract"
mathPerformer = Subtract;
Console.WriteLine(mathPerformer(2, 3)); // Output : -1
Console.ReadLine();
}
当您在程序已经运行之前不知道要使用什么特定算法或处理技术时,这很有用。委托(delegate)让我们选择我们想要指向的函数,然后我们可以在程序运行时执行它。
这一切与上面的 lambda 讨论相关的方式是,MatchEvaluator 不知道如何处理它在仔细阅读您的字符串时找到的每个匹配项。相反,通过向它提供 lambda/函数,您可以告诉它在找到匹配项时要使用的算法。基本上,委托(delegate)可用于在运行时确定您希望如何执行某些操作。
编辑: 如果您想扩展您的 lambda 表达式以包含不止一行代码,您也可以使用代码块。考虑:
String result = Regex.Replace(
text,
@"\[%RC:(\d+)%\]",
match => {
return dict[int.Parse(match.Groups[1].Value)]
});
您会注意到这里有两点不同。 (1) 我们的 => 现在跟在 { } 之后,它允许我们放入多行代码。因此,编译器不知道哪个值是返回值,因此无法推断返回类型是什么。因此,(2) 我们插入一个显式的 return 命令来指示应该返回哪个值。
使用这个简单的代码库,我们可以做如下事情:
String result = Regex.Replace(
text,
@"\[%RC:(\d+)%\]",
match => {
// This does the same thing, but with more lines of code.
// Of course, you could get way more fancy with it as well.
String numericValueAsString = match.Groups[1].Value;
Int32 numericValue = Int32.Parse(numericValueAsString);
String dictionaryValue = dict[numericValue];
// Same as above
return dictionaryValue;
});
关于c# - 有人可以为我分解这个 lambda 表达式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16677540/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的
我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:
我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的rubyyaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir