【发布时间】:2021-04-19 03:10:35
【问题描述】:
我正在想办法拆分以下字符串:
"2.000000, ["Me", [13, 11], "You"], [12.000000, 15.000000]"
这样我就有了一个包含以下内容的字符串向量:
2.000000
["Me", [13, 11], "You"]
[12.000000, 15.000000]
我开始使用 , 作为正则表达式,但是这会不恰当地拆分子列表 ([...])。
我该怎么做?
【问题讨论】:
我正在想办法拆分以下字符串:
"2.000000, ["Me", [13, 11], "You"], [12.000000, 15.000000]"
这样我就有了一个包含以下内容的字符串向量:
2.000000
["Me", [13, 11], "You"]
[12.000000, 15.000000]
我开始使用 , 作为正则表达式,但是这会不恰当地拆分子列表 ([...])。
我该怎么做?
【问题讨论】:
直接的解决方案是将[] 括号的余额存储在当前前缀上。 [ 给出 +1,] 给出 -1。也不要更新余额,忽略"strings"内的[和]
int balance = 0;
// If balance is 0, you're outside your list:
// [ ... ]
// ^ here ^ or here
// If balance is >= 1, you're inside list:
// [ ... ]
// ^^^
// If balance >= 2, you're inside sublist:
// [ ..., [ ..., [...] ], ... ]
// ^ balance == 2
// ^ balance == 3 and so on
// Ignore updating balance if [ and ] inside ""-s.
// E.g. balance won't increase
// ["["]
// ^ here
// Also ignore commas here: [",", ","]
// ^ ^
bool inside_string = false;
std::string current_part;
std::vector<std::string> parts;
for (char c : s) {
if (c == '"')
inside_string ^= true;
// Both comma and closing brace if balance is 1 can end current part.
// Current part can't end inside ""-s.
if (balance == 1 && (c == ',' || c == ']') && !inside_string) {
parts.push_back(std::move(current_part));
current_part = "";
continue;
}
if (balance >= 1) {
// No need to add space coming right after comma.
if (current_part.empty() && c == ' ')
continue;
current_part += c;
}
if (!inside_string) {
if (c == '[') {
++balance;
} else if (c == ']') {
--balance;
}
}
}
【讨论】:
用正则表达式匹配嵌套括号不是一个好方法。相反,您可以遍历字符串input,并简单地跟踪您当前是否在一对括号内。如果是,并且遇到,,则在该点拆分字符串,否则忽略,。
std::vector<std::string> result;
int prev = 0, in_brackets = 0;
for (int i = 0; i < std::ssize(input); ++i)
{
if (input[i] == ',' and not in_brackets)
{
result.push_back(input.substr(prev, prev - i));
prev = i + 1;
}
else if (input[i] == '[') in_brackets++; // 1 more level of brackets
else if (input[i] == ']') in_brackets--; // 1 less level of brackets
}
result.push_back(input.substr(prev)); // add the last chunk
std::ssize 是 C++20 的一项功能,它以有符号整数的形式返回范围的大小,这样处理起来要好得多。如果您没有 C++20,则使用 std::size,并将结果手动转换为 int。
【讨论】: