Это не так чисто, как использование итераторов, но вот одна из идей. Чтение ключей и значений затруднено, если вы читаете строку с самого начала из-за необходимости заглядывать вперед, чтобы определить, является ли то, что вы читаете, частью значения или следующим ключом.
Чтение строки в обратном направлении Однако намного проще. Последнее значение - это все после последнего ':'
. Последний ключ - это все от последнего ','
до этого до последнего ':'
.
Например, мы будем использовать вашу строку.
"key1:value1, key2:this is, some value2, key3:another val,ue,"
^ the last ':'
"key1:value1, key2:this is, some value2, key3:another val,ue,"
^ the last ',' before that
"key1:value1, key2:this is, some value2, key3:another val,ue,"
^ the last ':' before that
"key1:value1, key2:this is, some value2, key3:another val,ue,"
^ the last ',' before that
"key1:value1, key2:this is, some value2, key3:another val,ue,"
^ the last ':' before that
Как вы можете видеть, это прекрасно разбивает строку на ключи и значения.
Чтобы фактически закодировать это, у нас будет фрагмент, который всегда ссылается на ту часть строки, которая у нас есть. еще не покрыто. На каждом шаге мы найдем последний ':'
(или ','
) и изменим срез, чтобы указывать перед ним. Использование rsplitn
работает довольно хорошо, но я уверен, что есть и другой способ.
fn main() {
let mut kv = Vec::new();
let mut slice = "key1:value1, key2:this is, some value2, key3:another val,ue,";
while !slice.is_empty() {
let mut split = slice.rsplitn(2, ':');
// `rsplitn` will always return at least one slice,
// namely the whole string if there aren't any matches.
// So we can unwrap here.
let value = split.next().unwrap().trim();
// You may want to decide to do something else here.
// The only way `split.next()` will be `None` is if
// The input string has incorrect syntax.
slice = split.next().unwrap_or("");
let mut split = slice.rsplitn(2, ',');
// similar reasoning here
let key = split.next().unwrap().trim();
slice = split.next().unwrap_or("");
kv.push((key, value));
}
println!("{:?}", kv);
}
(игровая площадка)
Всего одна заметка. Код выше подсчитывает любые запятые как часть последнего значения. Если вы не хотите этого, вы можете сделать проверку. Не забудьте сначала trim
строку (и это может стоить сделать в любом случае)! В будущем strip_suffix
будет хорошо работать здесь. На данный момент, str::ends_with
должно подойти.