C# 如何为字符串格式提供自定义字符串占位符
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1102300/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to provide custom string placeholder for string format
提问by
I have a string
我有一个字符串
string str ="Enter {0} patient name";
I am using string.format to format it.
我正在使用 string.format 对其进行格式化。
String.Format(str, "Hello");
Now if i want patient also to be retrieved from some config then I need to change str to something like
"Enter {0} {1} name"
. So it will replace the {1} with second value. The problem is that I want instead of {1} some other format something like {pat}
. But when I try to use, it throws an error. The reason I want a different format is that there are lot of files I need to change like this(which may contain {0},{1} etc). So I need a custom placeholder which can be replaced at run-time.
现在,如果我还希望从某些配置中检索患者,那么我需要将 str 更改为类似
"Enter {0} {1} name"
. 因此它将用第二个值替换 {1}。问题是我想要而不是 {1} 其他格式,例如{pat}
. 但是当我尝试使用时,它会引发错误。我想要不同格式的原因是我需要像这样更改很多文件(可能包含 {0}、{1} 等)。所以我需要一个可以在运行时替换的自定义占位符。
回答by Marc Gravell
Regex
with a MatchEvaluator
seems a good option:
Regex
有MatchEvaluator
似乎是一个不错的选择:
static readonly Regex re = new Regex(@"\{([^\}]+)\}", RegexOptions.Compiled);
static void Main()
{
string input = "this {foo} is now {bar}.";
StringDictionary fields = new StringDictionary();
fields.Add("foo", "code");
fields.Add("bar", "working");
string output = re.Replace(input, delegate (Match match) {
return fields[match.Groups[1].Value];
});
Console.WriteLine(output); // "this code is now working."
}
回答by Magnus Lindhe
You might want to check out FormatWith 2.0by James Newton-King. It allows you to use property names as formatting tokens such as this:
你可能想看看FormatWith 2.0由詹姆斯·牛顿景。它允许您使用属性名称作为格式标记,例如:
var user = new User()
{
Name = "Olle Wobbla",
Age = 25
};
Console.WriteLine("Your name is {Name} and your age is {Age}".FormatWith(user));
You can also use it with anonymous types.
您也可以将它与匿名类型一起使用。
UPDATE:There is also a similar solutionby Scott Hanselmanbut it is implemented as a set of extension methods on Object
instead of String
.
更新:Scott Hanselman也有一个类似的解决方案,但它是作为一组扩展方法实现的,而不是.Object
String
UPDATE 2012: You can get Calrius Consulting's NETFx String.FormatWith Extension MethodNuGet package on NuGet.org
UPDATE 2012:你可以得到Calrius咨询的NETFX String.FormatWith扩展方法上的NuGet包NuGet.org
UPDATE 2014: There is also StringFormat.NETand littlebit's StringFormat
2014 年更新:还有StringFormat.NET和littlebit 的 StringFormat
回答by Dean Povey
You are probably better off using Replace for the custom field and Format for the rest, like:
您可能最好对自定义字段使用 Replace 并为其余部分使用 Format ,例如:
string str = "Enter {0} {pat} name";
String.Format(str.Replace("{pat}", "Patient"), "Hello");
回答by Chansik Im
I saw all the answers above, yet, couldn't get the question right :)
我看到了上面的所有答案,但是,无法回答正确的问题:)
Is there any particular reason why the following code does not meet your requirement?
以下代码不符合您的要求是否有任何特殊原因?
string myFirstStr = GetMyFirstStrFromSomewhere();
string mySecondStr = GetMySecondStrFromSomewhere();
string result = "Enter " + myFirstStr + " " + mySecondStr + " name";
回答by mujtaba Hyder
object[] myInts = new int[] {8,9};
However you can get away with:
但是你可以逃脱:
object[] myInts = new string[] { "8", "9" };
string bar = string.Format("{0} {1}", myInts);
回答by Bryan Legend
Here's another version of this that I found here: http://www.reddit.com/r/programming/comments/bodml/beef_up_params_in_c_5_to_solve_lambda_abuse/c0nrsf1
这是我在这里找到的另一个版本:http: //www.reddit.com/r/programming/comments/bodml/beef_up_params_in_c_5_to_solve_lambda_abuse/c0nrsf1
Any solution to this is going to involve reflection, which is less than ideal, but here's his code with some of the other major performance issues resolved. (No error checking. Add it if you like.):
对此的任何解决方案都将涉及反射,这不太理想,但这是他的代码,解决了其他一些主要的性能问题。(没有错误检查。如果你愿意,可以添加它。):
1) Uses direct runtime reflection, no DataBinder overhead
1) 使用直接运行时反射,没有 DataBinder 开销
2) Doesn't use regular expressions, uses a single-pass parse and state.
2) 不使用正则表达式,使用单通道解析和状态。
3) Doesn't convert the string into an intermediate string and then convert it again to the final format.
3) 不将字符串转换为中间字符串,然后再将其转换为最终格式。
4) Allocates and concatenates with a single StringBuilder instead of newing up strings all over the place and concatenating them into new strings.
4) 使用单个 StringBuilder 分配和连接而不是在整个地方更新字符串并将它们连接成新字符串。
5) Removes the stack overhead of calling a delegate for n replace operations.
5) 移除为 n 次替换操作调用委托的堆栈开销。
6) In general is a single pass through that will scale in a relatively linear manner (still some cost for each prop lookup and nested prop lookup, but that's that.)
6)通常是单次通过,它将以相对线性的方式扩展(每个道具查找和嵌套道具查找仍然有一些成本,但仅此而已。)
public static string FormatWith(this string format, object source)
{
StringBuilder sbResult = new StringBuilder(format.Length);
StringBuilder sbCurrentTerm = new StringBuilder();
char[] formatChars = format.ToCharArray();
bool inTerm = false;
object currentPropValue = source;
for (int i = 0; i < format.Length; i++)
{
if (formatChars[i] == '{')
inTerm = true;
else if (formatChars[i] == '}')
{
PropertyInfo pi = currentPropValue.GetType().GetProperty(sbCurrentTerm.ToString());
sbResult.Append((string)(pi.PropertyType.GetMethod("ToString", new Type[]{}).Invoke(pi.GetValue(currentPropValue, null), null)));
sbCurrentTerm.Clear();
inTerm = false;
currentPropValue = source;
}
else if (inTerm)
{
if (formatChars[i] == '.')
{
PropertyInfo pi = currentPropValue.GetType().GetProperty(sbCurrentTerm.ToString());
currentPropValue = pi.GetValue(source, null);
sbCurrentTerm.Clear();
}
else
sbCurrentTerm.Append(formatChars[i]);
}
else
sbResult.Append(formatChars[i]);
}
return sbResult.ToString();
}
回答by Ole K
You can also use the example from Marc Gravell and Extend the String class object:
您还可以使用 Marc Gravell 中的示例并扩展 String 类对象:
public static class StringExtension
{
static readonly Regex re = new Regex(@"\{([^\}]+)\}", RegexOptions.Compiled);
public static string FormatPlaceholder(this string str, Dictionary<string, string> fields)
{
if (fields == null)
return str;
return re.Replace(str, delegate(Match match)
{
return fields[match.Groups[1].Value];
});
}
}
Example usage:
用法示例:
String str = "I bought a {color} car";
Dictionary<string, string> fields = new Dictionary<string, string>();
fields.Add("color", "blue");
str.FormatPlaceholder(fields));
回答by samwyse
I wanted something that worked more like Python's string formatting, so I wrote this: https://gist.github.com/samwyse/b225b32ae1aea6fb27ad9c966b9ca90b
我想要一些更像 Python 字符串格式的东西,所以我写了这个:https: //gist.github.com/samwyse/b225b32ae1aea6fb27ad9c966b9ca90b
Use it like this:
像这样使用它:
Dim template = New FormatFromDictionary("{cat} vs {dog}")
Dim d = New Dictionary(Of String, Object) From {
{"cat", "Felix"}, {"dog", "Rex"}}
Console.WriteLine(template.Replace(d)) ' Felix vs Rex