通用模板字符串,例如Dart中的Python

Generic Template String like in Python in Dart

在python中,我经常使用字符串作为模板,例如

1
2
3
templateUrl = '{host}/api/v3/{container}/{resourceid}'  
params = {'host': 'www.api.com', 'container': 'books', 'resourceid': 10}  
api.get(templateUrl.format(**params))

这允许简单的基类设置等。 如何在飞镖上做同样的事情?

我假设我将需要创建一个实用程序函数来解析模板并手动替换,但实际上希望有一些可用的东西。

可能是带有format方法的TemplateString类,该方法采用名称/值对的Map替换为字符串。

注意:目标是拥有通用的"格式"或"插值"功能,而无需事先知道模板中将存在哪些标记或名称。

进一步说明:模板本身在设置时不会解析。 具体来说,模板是在代码中的一个位置定义的,然后在许多其他位置使用。


Dart没有通用的模板字符串功能,该功能允许您在运行时将值插入模板。
Dart仅允许您使用字符串中的$语法用变量对字符串进行插值,例如var string = '$domain/api/v3/${actions.get}'。您需要事先在代码中定义所有变量。

但是,您可以轻松创建自己的实现。

实作

您几乎已经在自己的问题中解释了如何执行此操作:您传递了一个映射,并使用它使用[]运算符来通用访问参数。

要将模板字符串转换为易于访问的内容,我只需创建另一个包含固定组件的List,例如/api/v3/和另一个Map即可保存通用组件及其名称和它们在模板字符串中的位置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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;
  }
}

这将是一个示例用法,我希望结果是您期望的:

1
2
3
4
5
6
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
}

这里是要点。


在Dart中更容易。下面的示例代码:

1
2
3
4
5
String host ="www.api.com"
String container ="books"
int resourceId = 10

String templateUrl ="$host/api/v3/$container/${resourceId.toString()}"

使用地图,您可以执行以下操作:

1
2
3
Map<String, String> params = {'host': 'www.api.com', 'container': 'books', 'resourceid': 10}  

String templateUrl ="${params['host']}/api/v3/${params['container']}/${params['resourceId']}"

注意:上面的代码将Map定义为。您可能需要(并使用.toString())