通用模板字符串,如 Dart 中的 Python
Generic Template String like in Python in Dart
在python中,我经常使用字符串作为模板,例如
templateUrl = '{host}/api/v3/{container}/{resourceid}'
params = {'host': 'www.api.com', 'container': 'books', 'resourceid': 10}
api.get(templateUrl.format(**params))
这允许简单的基础 class 设置等。我怎样才能在飞镖中做同样的事情?
我假设我需要创建一个实用函数来解析模板并手动替换,但真的希望有现成的东西可以使用。
也许是一个带有 format
方法的 TemplateString class,该方法采用 Map
对 name/value 来替换字符串。
注意:objective 具有通用的“格式”或“插值”功能,不需要事先知道模板中将存在哪些标签或名称。
进一步说明:模板本身在设置时并未解析。具体来说,模板在代码中的一个地方定义,然后在其他许多地方使用。
在 Dart 中更容易。示例代码如下:
String host = "www.api.com"
String container = "books"
int resourceId = 10
String templateUrl = "$host/api/v3/$container/${resourceId.toString()}"
有了地图,您可以进行如下操作:
Map<String, String> params = {'host': 'www.api.com', 'container': 'books', 'resourceid': 10}
String templateUrl = "${params['host']}/api/v3/${params['container']}/${params['resourceId']}"
注意:以上代码将Map定义为<String, String>
。您可能需要 <String, Dynamic>
(并使用 .toString()
)
Dart 没有允许您在 运行时.
将值插入模板的通用模板字符串功能
Dart 只允许您使用 $
语法在字符串中插入带有变量的字符串,例如var string = '$domain/api/v3/${actions.get}'
。您需要事先在代码中定义所有变量。
但是,您可以轻松创建自己的实现。
实施
您在自己的问题中几乎已经解释了如何做到这一点:您传递一个映射并使用它来使用 []
运算符对参数进行通用访问。
为了将模板字符串转换成易于访问的内容,我会简单地创建另一个包含固定组件的 List
,例如 /api/v3/
和另一个包含通用组件的 Map
他们的名字和他们在模板字符串中的位置。
class TemplateString {
final List<String> fixedComponents;
final Map<int, String> genericComponents;
int totalComponents;
TemplateString(String template)
: fixedComponents = <String>[],
genericComponents = <int, String>{},
totalComponents = 0 {
final List<String> components = template.split('{');
for (String component in components) {
if (component == '') continue; // If the template starts with "{", skip the first element.
final split = component.split('}');
if (split.length != 1) {
// The condition allows for template strings without parameters.
genericComponents[totalComponents] = split.first;
totalComponents++;
}
if (split.last != '') {
fixedComponents.add(split.last);
totalComponents++;
}
}
}
String format(Map<String, dynamic> params) {
String result = '';
int fixedComponent = 0;
for (int i = 0; i < totalComponents; i++) {
if (genericComponents.containsKey(i)) {
result += '${params[genericComponents[i]]}';
continue;
}
result += fixedComponents[fixedComponent++];
}
return result;
}
}
下面是一个使用示例,希望结果如您所愿:
main() {
final templateUrl = TemplateString('{host}/api/v3/{container}/{resourceid}');
final params = <String, dynamic>{'host': 'www.api.com', 'container': 'books', 'resourceid': 10};
print(templateUrl.format(params)); // www.api.com/api/v3/books/10
}
这里是as a Gist。
这是我的解决方案:
extension StringFormating on String {
String format(List<String> values) {
int index = 0;
return replaceAllMapped(new RegExp(r'{.*?}'), (_) {
final value = values[index];
index++;
return value;
});
}
String formatWithMap(Map<String, String> mappedValues) {
return replaceAllMapped(new RegExp(r'{(.*?)}'), (match) {
final mapped = mappedValues[match[1]];
if (mapped == null)
throw ArgumentError(
'$mappedValues does not contain the key "${match[1]}"');
return mapped;
});
}
}
这为您提供了与 python 提供的非常相似的功能:
"Test {} with {}!".format(["it", "foo"]);
"Test {a} with {b}!".formatWithMap({"a": "it", "b": "foo"})
两者都 return“用 foo 测试它!”
在python中,我经常使用字符串作为模板,例如
templateUrl = '{host}/api/v3/{container}/{resourceid}'
params = {'host': 'www.api.com', 'container': 'books', 'resourceid': 10}
api.get(templateUrl.format(**params))
这允许简单的基础 class 设置等。我怎样才能在飞镖中做同样的事情?
我假设我需要创建一个实用函数来解析模板并手动替换,但真的希望有现成的东西可以使用。
也许是一个带有 format
方法的 TemplateString class,该方法采用 Map
对 name/value 来替换字符串。
注意:objective 具有通用的“格式”或“插值”功能,不需要事先知道模板中将存在哪些标签或名称。
进一步说明:模板本身在设置时并未解析。具体来说,模板在代码中的一个地方定义,然后在其他许多地方使用。
在 Dart 中更容易。示例代码如下:
String host = "www.api.com"
String container = "books"
int resourceId = 10
String templateUrl = "$host/api/v3/$container/${resourceId.toString()}"
有了地图,您可以进行如下操作:
Map<String, String> params = {'host': 'www.api.com', 'container': 'books', 'resourceid': 10}
String templateUrl = "${params['host']}/api/v3/${params['container']}/${params['resourceId']}"
注意:以上代码将Map定义为<String, String>
。您可能需要 <String, Dynamic>
(并使用 .toString()
)
Dart 没有允许您在 运行时.
将值插入模板的通用模板字符串功能
Dart 只允许您使用 $
语法在字符串中插入带有变量的字符串,例如var string = '$domain/api/v3/${actions.get}'
。您需要事先在代码中定义所有变量。
但是,您可以轻松创建自己的实现。
实施
您在自己的问题中几乎已经解释了如何做到这一点:您传递一个映射并使用它来使用 []
运算符对参数进行通用访问。
为了将模板字符串转换成易于访问的内容,我会简单地创建另一个包含固定组件的 List
,例如 /api/v3/
和另一个包含通用组件的 Map
他们的名字和他们在模板字符串中的位置。
class TemplateString {
final List<String> fixedComponents;
final Map<int, String> genericComponents;
int totalComponents;
TemplateString(String template)
: fixedComponents = <String>[],
genericComponents = <int, String>{},
totalComponents = 0 {
final List<String> components = template.split('{');
for (String component in components) {
if (component == '') continue; // If the template starts with "{", skip the first element.
final split = component.split('}');
if (split.length != 1) {
// The condition allows for template strings without parameters.
genericComponents[totalComponents] = split.first;
totalComponents++;
}
if (split.last != '') {
fixedComponents.add(split.last);
totalComponents++;
}
}
}
String format(Map<String, dynamic> params) {
String result = '';
int fixedComponent = 0;
for (int i = 0; i < totalComponents; i++) {
if (genericComponents.containsKey(i)) {
result += '${params[genericComponents[i]]}';
continue;
}
result += fixedComponents[fixedComponent++];
}
return result;
}
}
下面是一个使用示例,希望结果如您所愿:
main() {
final templateUrl = TemplateString('{host}/api/v3/{container}/{resourceid}');
final params = <String, dynamic>{'host': 'www.api.com', 'container': 'books', 'resourceid': 10};
print(templateUrl.format(params)); // www.api.com/api/v3/books/10
}
这里是as a Gist。
这是我的解决方案:
extension StringFormating on String {
String format(List<String> values) {
int index = 0;
return replaceAllMapped(new RegExp(r'{.*?}'), (_) {
final value = values[index];
index++;
return value;
});
}
String formatWithMap(Map<String, String> mappedValues) {
return replaceAllMapped(new RegExp(r'{(.*?)}'), (match) {
final mapped = mappedValues[match[1]];
if (mapped == null)
throw ArgumentError(
'$mappedValues does not contain the key "${match[1]}"');
return mapped;
});
}
}
这为您提供了与 python 提供的非常相似的功能:
"Test {} with {}!".format(["it", "foo"]);
"Test {a} with {b}!".formatWithMap({"a": "it", "b": "foo"})
两者都 return“用 foo 测试它!”