I'm loosing my mind with this (because I'm not a very logic person).
I cannot change the data part.
The string returned from the below code is A = 1 AND (B = 2 OR C = 3 OR D = 4 OR )
instead of what I need (A = 1 AND (B = 2 OR C = 3 OR D = 4)
).
What I don't understand is how to avoid the last "OR".
How can I fix the below code?
enum Token {
Str(&'static str),
Value(&'static str),
StartGroup(&'static str),
EndGroup,
}
fn main() {
let data: Vec<Vec<Token>> = vec![
vec![Token::Str("A = "), Token::Value("1")],
vec![Token::Str(" AND ("), Token::StartGroup(" OR ")],
vec![Token::Str("B = "), Token::Value("2")],
vec![Token::Str("C = "), Token::Value("3")],
vec![Token::Str("D = "), Token::Value("4")],
vec![Token::EndGroup, Token::Str(")")],
];
let result = construct_string(data);
assert_eq!("A = 1 AND (B = 2 OR C = 3 OR D = 4)", result);
}
fn construct_string(tokens: Vec<Vec<Token>>) -> String {
let mut result = String::new();
let mut current = String::new();
let mut next = String::new();
for token in tokens {
for part in token {
match part {
Token::Str(str) => {
result.push_str(str);
}
Token::Value(val) => {
result.push_str(val);
}
Token::StartGroup(group) => {
next = group.to_string();
}
Token::EndGroup => {
current = String::new();
next = String::new();
}
}
}
if !current.is_empty() {
result.push_str(¤t);
}
current = next.to_string();
}
result
}
I moved EndGroup
to the previous vector and it worked:
enum Token {
Str(&'static str),
Value(&'static str),
StartGroup(&'static str),
EndGroup,
}
fn main() {
let data: Vec<Vec<Token>> = vec![
vec![Token::Str("A = "), Token::Value("1")],
vec![Token::Str(" AND ("), Token::StartGroup(" OR ")],
vec![Token::Str("B = "), Token::Value("2")],
vec![Token::Str("C = "), Token::Value("3")],
vec![Token::Str("D = "), Token::Value("4"), Token::EndGroup],
vec![ Token::Str(")")],
];
let result = construct_string(data);
assert_eq!("A = 1 AND (B = 2 OR C = 3 OR D = 4)", result);
}
fn construct_string(tokens: Vec<Vec<Token>>) -> String {
let mut result = String::new();
let mut current = String::new();
let mut next = String::new();
for token in tokens {
for part in token {
match part {
Token::Str(str) => {
result.push_str(str);
}
Token::Value(val) => {
result.push_str(val);
}
Token::StartGroup(group) => {
next = group.to_string();
}
Token::EndGroup => {
current = String::new();
next = String::new();
}
}
}
if !current.is_empty() {
result.push_str(¤t);
}
current = next.to_string();
}
result
}
EDIT
Applied a fix inside construct_string
, please take a look (the idea is to differentiate whether the delimiter has to appear):
enum Token {
Str(&'static str),
Value(&'static str),
StartGroup(&'static str),
EndGroup,
}
fn main() {
let data: Vec<Vec<Token>> = vec![
vec![Token::Str("A = "), Token::Value("1")],
vec![Token::Str(" AND ("), Token::StartGroup(" OR ")],
vec![Token::Str("B = "), Token::Value("2")],
vec![Token::Str("C = "), Token::Value("3")],
vec![Token::Str("D = "), Token::Value("4")],
vec![Token::EndGroup, Token::Str(")")],
];
let result = construct_string(data);
assert_eq!("A = 1 AND (B = 2 OR C = 3 OR D = 4)", result);
}
fn construct_string(tokens: Vec<Vec<Token>>) -> String {
let mut result = String::new();
//let mut current = String::new();
let mut next = String::new();
let mut new_group = true;
for token in tokens {
for part in token {
match part {
Token::Str(str) => {
if !new_group {
result.push_str(&next);
}
new_group = false;
result.push_str(str);
}
Token::Value(val) => {
result.push_str(val);
}
Token::StartGroup(group) => {
new_group = true;
next = group.to_string();
}
Token::EndGroup => {
//current = String::new();
next = String::new();
}
}
}
//if !current.is_empty() {
// result.push_str(¤t);
//}
//current = next.to_string();
}
result
}