let vec = iter::repeat("don't satisfy condition 1") // iterator such as next() always "don't " satisfy condition 1"
.take_while(|_| {
satisfycondition1.satisfy() // true is condition 1 is satisfied else false
})
.collect();
This code creates a vector of n elements with n equal to the number of times condition 1 is not respected.
I would like now to create a vector of n + m elements with n equal to the number of times that condition 1 is not respected and m the number of times that condition 2 is not respected.
The code should look like something like this:
let vec = iter::repeat("dont't satisfy condition 1")
.take_while(|_| {
satisfycondition1.satisfy()
})
.union(
iter::repeat("has satisfed condition 1 but not 2 yet")
.take_while(|_| {
satisfycondition2.satisfy()
})
)
.collect();
I know I could create two vectors and then concatenate them but it's less efficient.
You can use this code to understand what does repeat:
use std::iter;
fn main() {
let mut c = 0;
let z: Vec<_> = iter::repeat("dont't satisfy condition 1")
.take_while(|_| {
c = c + 1;
let rep = if c < 5 { true } else { false };
rep
})
.collect();
println!("------{:?}", z);
}
It seems like std::iter::chain is what you're looking for.
use std::iter;
fn main() {
let mut c = 0;
let mut d = 5;
let z: Vec<_> = iter::repeat("don't satisfy condition 1")
.take_while(|_| {
c = c + 1;
let rep = if c < 5 { true } else { false };
rep
// this block can be simplified to
// c += 1;
// c < 5
// Clippy warns about this
})
.chain(
iter::repeat("satisfy condition 1 but not 2").take_while(|_| {
d -= 1;
d > 2
}),
)
.collect();
println!("------{:?}", z);
}
(playground link)
I can't comment on the semantics of your code, though. If you're trying to see which elements of an iterator "satisfy condition 1 but not 2", this wouldn't be how you do it. You would use std::iter::filter twice (once with condition 1 and once with not condition 2) to achieve that.
Related
In Rust, in order to change the value of a mutable variable, what is the difference in let x = 12 or x = 12 in the following sample code?
fn main() {
let mut x: i32 = 8;
{
println!("{}", x);
let x = 12; // what if change to x = 12
println!("{}", x);
}
println!("{}", x);
let x = 42;
println!("{}", x);
}
The output is 8, 12, 8, 42. If I change let x = 12 to x = 12 ...
fn main() {
let mut x: i32 = 8;
{
println!("{}", x);
x = 12;
println!("{}", x);
}
println!("{}", x);
let x = 42;
println!("{}", x);
}
The output is 8, 12, 12, 42.
I understand that Rust uses let to do variable binding, so the let x = 12 is a variable rebinding and the binding is only valid inside a scope. But how to explain the functionality of x = 12 and the corresponding scope? Is that a type of variable binding?
The second let x introduces a second binding that shadows the first one for the rest of the block. That is, there are two variables named x, but you can only access the second one within the block statement after the let x = 12; statement. These two variables don't need to have the same type!
Then, after the block statement, the second x is out of scope, so you access the first x again.
However, if you write x = 12; instead, that's an assignment expression: the value in x is overwritten. This doesn't introduce a new variable, so the type of the value being assigned must be compatible with the variable's type.
This difference is important if you write a loop. For example, consider this function:
fn fibonacci(mut n: u32) -> u64 {
if n == 0 {
return 1;
}
let mut a = 1;
let mut b = 1;
loop {
if n == 1 {
return b;
}
let next = a + b;
a = b;
b = next;
n -= 1;
}
}
This function reassigns variables, so that each iteration of the loop can operate on the values assigned on the preceding iteration.
However, you might be tempted to write the loop like this:
loop {
if n == 1 {
return b;
}
let (a, b) = (b, a + b);
n -= 1;
}
This doesn't work, because the let statement introduces new variables, and these variables will go out of scope before the next iteration begins. On the next iteration, (b, a + b) will still use the original values.
So basically, I want to do this
for i=0;i<x.len()-1
for j=i;j<x.len
//do stuff with x[j] and x[i] at the same time
For example, I want to use the same tehnique as sorting using 2 for loops, comparing element with element and interchange them. I do not want to sort however, just gave this example for better understanding.
Can i somehow do like:
for x in vec.iter()
for y in x.next()
or something like this?
Also, can I somehow remember the position of a certain element while iterating?
Thank you!
You could use ranges
for i in 0..vec.len()-1 {
for j in i..vec.len() {
// do something with vec[i] and vec[j]
}
}
Your suggested code:
for x in vec.iter()
for y in x.next()
wouldn't work even if it were syntactically valid because x is not an iterator, it's an element of vec. To get at the iterator, you need to store it in a variable and desugar the for loop into while let:
let mut iter = v.iter();
while let Some(x) = iter {
// ...
}
Now that we have an explicit iter, we can make the inner loop iterate over the remaining items. We can't just iterate over iter because that would exhaust it for the outer loop, but we can clone it to obtain a copy of the outer iterator at its current position:
let mut iter = v.iter();
while let Some(x) = iter {
for y in iter.clone() {
// ...
}
}
Note that we don't need to explicitly call iter.next() before the inner loop, as the first item will have already been spent by the outer loop, and the inner loop will naturally observe only the remaining items of each iteration.
Complete code would look like this:
let v = vec![1, 2, 3];
let mut iter = v.iter();
while let Some(x) = iter.next() {
println!("x = {}", x);
for y in iter.clone() {
println!(" y = {}", y);
}
}
Output:
x = 1
y = 2
y = 3
x = 2
y = 3
x = 3
I need to detect and list string characters of slice that repeat themselves in order more or equal than N times. I managed to write non-higher-order-function solution in Rust already (below), but I wonder if this can be simplified to chaining iter methods.
The idea:
let v = "1122253225";
let n = 2;
Output:
There are 2 repetition of '1'
There are 3 repetition of '2'
There are 2 repetition of '2'
Indexes where repetition happens are not important. Repetition must happen in order (ie. 3 repetition of '2' separated by other values from the other 2 repetition of '2' counts as separate output lines).
My non-iterator solution:
let mut cur_ch = '\0';
let mut repeat = 0;
for ch in v.chars() {
if ch == cur_ch {
repeat = repeat + 1;
}
else {
if repeat >= n {
printf!("There are {} repetition of '{}'", repeat, cur_ch);
}
cur_ch = ch;
repeat = 1;
}
}
if repeat >= n {
printf!("There are {} repetition of '{}'", repeat, cur_ch);
}
It works, but is there a better way to do so with chaining iter methods?
Here is a solution that uses scan and filter_map:
fn main() {
let s = "112225322555";
let n = 2;
let i = s
.chars()
.map(|v| Some(v))
.chain(std::iter::once(None))
.scan((0, None), |(count, ch), v| match ch {
Some(c) if *c == v => {
*count += 1;
Some((None, *count))
}
_ => Some((ch.replace(v), std::mem::replace(count, 1))),
})
.filter_map(|(ch, count)| match ch {
Some(Some(ch)) if count >= n => Some((ch, count)),
_ => None,
});
for (ch, num) in i {
println!("There are {} repititions of {}", num, ch);
}
}
Playground Link
The first step is to use scan to count the number of adjacent characters. The first argument to scan is a state variable, which gets passed to each call of the closure that you pass as the second argument. In this case the state variable is a tuple containing the current character and the number of times it has been seen.
Note:
We need to extend the iteration one beyond the end of the string we are analyzing (otherwise we would miss the case where the end of the string contained a run of characters meeting the criteria). We do this by mapping the iteration into Option<char> and then chaining on a single None. This is better than special-casing a character such as \0, so that we could even count \0 characters.
For the same reason, we use Option<char> as the current character within the state tuple.
The return value of scan is an iterator over (Option<Option<char>>, i32). The first value in the tuple will be None for each repeated character in the iterator, whereas at each boundary where the character changes it will be Some(Some(char))
We use replace to both return the current character and count, at the same time as setting the state tuple to new values
The last step is to use filter_map to:
remove the (None, i32) variants, which indicate no change in the incoming character
filter out the cases where the count does not reach the limit n.
Here's one attempt at using filter_map():
fn foo(v: &str, n: usize) -> impl Iterator<Item = (usize, char)> + '_ {
let mut cur_ch = '\0';
let mut repeat = 0;
v.chars().chain(std::iter::once('\0')).filter_map(move |ch| {
if ch == cur_ch {
repeat += 1;
return None;
}
let val = if repeat >= n {
Some((repeat, cur_ch))
} else {
None
};
cur_ch = ch;
repeat = 1;
val
})
}
fn main() {
for (repeat, ch) in foo("1122253225", 2) {
println!("There are {} repetition of '{}'", repeat, ch);
}
}
And then you can generalize this to something like this:
fn foo<'i, I, T>(v: I, n: usize) -> impl Iterator<Item = (usize, T)> + 'i
where
I: Iterator<Item = T> + 'i,
T: Clone + Default + PartialEq + 'i,
{
let mut cur = T::default();
let mut repeat = 0;
v.chain(std::iter::once(T::default()))
.filter_map(move |i| {
if i == cur {
repeat += 1;
return None;
}
let val = if repeat >= n {
Some((repeat, cur.clone()))
} else {
None
};
cur = i;
repeat = 1;
val
})
}
This would be higher-order, but not sure if it's actually much simpler than just using a for loop!
In Rust, in order to change the value of a mutable variable, what is the difference in let x = 12 or x = 12 in the following sample code?
fn main() {
let mut x: i32 = 8;
{
println!("{}", x);
let x = 12; // what if change to x = 12
println!("{}", x);
}
println!("{}", x);
let x = 42;
println!("{}", x);
}
The output is 8, 12, 8, 42. If I change let x = 12 to x = 12 ...
fn main() {
let mut x: i32 = 8;
{
println!("{}", x);
x = 12;
println!("{}", x);
}
println!("{}", x);
let x = 42;
println!("{}", x);
}
The output is 8, 12, 12, 42.
I understand that Rust uses let to do variable binding, so the let x = 12 is a variable rebinding and the binding is only valid inside a scope. But how to explain the functionality of x = 12 and the corresponding scope? Is that a type of variable binding?
The second let x introduces a second binding that shadows the first one for the rest of the block. That is, there are two variables named x, but you can only access the second one within the block statement after the let x = 12; statement. These two variables don't need to have the same type!
Then, after the block statement, the second x is out of scope, so you access the first x again.
However, if you write x = 12; instead, that's an assignment expression: the value in x is overwritten. This doesn't introduce a new variable, so the type of the value being assigned must be compatible with the variable's type.
This difference is important if you write a loop. For example, consider this function:
fn fibonacci(mut n: u32) -> u64 {
if n == 0 {
return 1;
}
let mut a = 1;
let mut b = 1;
loop {
if n == 1 {
return b;
}
let next = a + b;
a = b;
b = next;
n -= 1;
}
}
This function reassigns variables, so that each iteration of the loop can operate on the values assigned on the preceding iteration.
However, you might be tempted to write the loop like this:
loop {
if n == 1 {
return b;
}
let (a, b) = (b, a + b);
n -= 1;
}
This doesn't work, because the let statement introduces new variables, and these variables will go out of scope before the next iteration begins. On the next iteration, (b, a + b) will still use the original values.
I have specified a few features inside Cargo.toml:
[features]
complex = []
simple = []
When I build my project I use cargo build --features="complex" or simple.
In some functions, I want to return a value based on which feature is used:
fn test() -> u32 {
let x: u32 = 3;
if cfg!(feature = "complex") {
let y: u32 = 2;
x + y
}
if cfg!(feature = "simple") {
let y: u32 = 1;
x + y
}
}
But this doesn't work as it tries to evaluate both expressions. What is the proper way to use the cfg! macro in my case?
The documentation for cfg! states:
Boolean evaluation of configuration flags.
That means that cfg!(...) is replaced with a Boolean (true / false). Your code would look something like this, after it's expanded:
fn test() -> u32 {
let x = 3;
if true {
let y = 2;
x + y
}
if true {
let y = 1;
x + y
}
}
The easiest solution is to add an else:
fn test() -> u32 {
let x = 3;
if cfg!(feature = "complex") {
let y = 2;
x + y
} else {
let y = 1;
x + y
}
}
You can also use the attribute form of cfg. In this case, the attribute can prevent the entire next expression from being compiled:
fn test() -> u32 {
let x: u32 = 3;
#[cfg(feature = "complex")]
{
let y: u32 = 2;
x + y
}
#[cfg(feature = "simple")]
{
let y: u32 = 1;
x + y
}
}
as it tries to evaluate both expressions.
No, it doesn't. Evaluation occurs at run-time, and this code cannot even be compiled.
See also:
Is it possible to conditionally compile a code block inside a function?
Example of how to use Conditional Compilation Macros in Rust
How many lines are covered by the Rust conditional compilation attribute?