//! 261. Lookahead with Peekable
//!
//! `Peekable` adds `peek()` to inspect the next element without consuming it.
fn main() {
let mut iter = [1i32, 2, 3, 4, 5].iter().peekable();
println!("Peek: {:?}", iter.peek());
println!("Next: {:?}", iter.next());
println!("Peek: {:?}", iter.peek());
println!("Next: {:?}", iter.next());
// Group consecutive equal elements
let data = [1i32, 1, 2, 2, 2, 3, 1, 1];
let mut iter = data.iter().peekable();
let mut groups: Vec<Vec<i32>> = Vec::new();
while let Some(&val) = iter.peek() {
let mut group = Vec::new();
while iter.peek() == Some(&val) {
group.push(*iter.next().unwrap());
}
groups.push(group);
}
println!("Groups: {:?}", groups);
// Tokenizer: parse runs of digits
let input: Vec<char> = "123abc456".chars().collect();
let mut it = input.iter().peekable();
let mut tokens: Vec<String> = Vec::new();
while it.peek().is_some() {
if it.peek().unwrap().is_ascii_digit() {
let digits: String = std::iter::from_fn(|| {
if it.peek().map(|c| c.is_ascii_digit()).unwrap_or(false) {
it.next().copied()
} else { None }
}).collect();
tokens.push(format!("NUM:{}", digits));
} else {
tokens.push(format!("CHAR:{}", it.next().unwrap()));
}
}
println!("Tokens: {:?}", tokens);
}
#[cfg(test)]
mod tests {
#[test]
fn test_peek_no_consume() {
let mut iter = [1i32, 2, 3].iter().peekable();
let p = iter.peek().copied().copied();
let n = iter.next().copied();
assert_eq!(p, Some(1));
assert_eq!(n, Some(1));
assert_eq!(iter.next().copied(), Some(2));
}
#[test]
fn test_peek_groups() {
let data = [1i32, 1, 2, 3, 3];
let mut iter = data.iter().peekable();
let mut groups: Vec<Vec<i32>> = Vec::new();
while let Some(&val) = iter.peek() {
let mut g = Vec::new();
while iter.peek() == Some(&val) { g.push(*iter.next().unwrap()); }
groups.push(g);
}
assert_eq!(groups, vec![vec![1,1], vec![2], vec![3,3]]);
}
#[test]
fn test_peek_empty() {
let data: Vec<i32> = vec![];
let mut p = data.iter().peekable();
assert_eq!(p.peek(), None);
}
}
(* 261. Lookahead with Peekable - OCaml *)
type 'a peekable = {
mutable peeked: 'a option;
mutable rest: 'a list;
}
let make_peekable lst = { peeked = None; rest = lst }
let peek p =
match p.peeked with
| Some _ as v -> v
| None ->
(match p.rest with
| [] -> None
| x :: _ -> p.peeked <- Some x; Some x)
let next p =
match p.peeked with
| Some v -> p.peeked <- None; (match p.rest with _ :: xs -> p.rest <- xs | [] -> ()); Some v
| None ->
match p.rest with
| [] -> None
| x :: xs -> p.rest <- xs; Some x
let () =
let p = make_peekable [1; 2; 3; 4; 5] in
Printf.printf "Peek: %s\n" (match peek p with Some n -> string_of_int n | None -> "None");
Printf.printf "Next: %s\n" (match next p with Some n -> string_of_int n | None -> "None");
Printf.printf "Next: %s\n" (match next p with Some n -> string_of_int n | None -> "None");
let p2 = make_peekable [1; 1; 2; 2; 3] in
let rec group_eq () =
match next p2 with
| None -> []
| Some x ->
let rec collect acc =
match peek p2 with
| Some y when y = x -> ignore (next p2); collect (x :: acc)
| _ -> List.rev (x :: acc)
in
collect [] :: group_eq ()
in
let groups = group_eq () in
List.iter (fun g ->
Printf.printf "[%s] " (String.concat ";" (List.map string_of_int g))
) groups;
print_newline ()