Stack Overflow Asked by GirkovArpa on February 26, 2021
I’m trying to print the first number in the array that isn’t exactly 1
greater than the previous number (expected result is 7
in the following example).
I wrote &n > 0 &&
to avoid checking the (non-existent) number before the first number.
fn main() {
let numbers = [4, 5, 7];
let result = numbers.iter().position(|&n| &n > 0 && n != numbers[&n - 1] + 1);
println!("{:?}", result);
}
I get this compiler error regarding the 0
:
expected reference, found integer
help: consider borrowing here:
&0
Basically I’m trying to do what this JavaScript does:
numbers.find((n, i) => i && n != numbers[i - 1] + 1);
Can someone tell me what I’m doing wrong?
I’m assuming that n
is the value and &n
is the index. If that isn’t correct then how do I get the index inside the lamba?
Another way to look at each pair of two consecutive items in a slice the windows(2)
iterator:
fn find_non_consecutive(a: &[i32]) -> Option<i32> {
a.windows(2).find(|x| x[0] + 1 != x[1]).map(|x| x[1])
}
Correct answer by Sven Marnach on February 26, 2021
I struggled hard to create a separate function that could be used as I wanted, so here is what ended up working:
fn find_non_consecutive(array_of_numbers: &[i32; 3]) -> Option<i32> {
let result = array_of_numbers.iter().enumerate().find_map(|(i, &n)| {
if i > 0 && n != array_of_numbers[i - 1] + 1 {
Some(n)
} else {
None
}
});
return result;
}
fn main() {
let numbers: [i32; 3] = [4, 5, 7];
let result = find_non_consecutive(&numbers);
println!("{:?}", result); // Some(7)
}
Answered by GirkovArpa on February 26, 2021
If you take a look at the signature of Iterator::position
, you will see that its predicate
closure parameter implements FnMut(Self::Item) -> bool
.
In other words, your argument &n
is of type <numbers.iter() as Iterator>::Item
i.e. &i32
(a reference to an element of numbers
). Iterator::position
does not provide its predicate
closure with access to the iteration index—as Psidom has demonstrated, that's what Iterator::enumerate
does.
However, I would suggest that indexing the numbers
array is not a very idiomatic way to solve this problem. If nothing else, it can't be applied to other iterables more generally. Perhaps instead take two iterators over the array, one an element further along, zip them up and pairwise compare their elements?
fn main() {
let numbers = [4, 5, 7];
let first = numbers.iter();
let second = numbers.iter().skip(1);
let result = first.zip(second)
.find_map(|(&a, &b)| if b == a + 1 { None } else { Some(b) });
println!("{:?}", result);
}
See it on the playground.
Answered by eggyal on February 26, 2021
position
is used to search element. Since you need to check all elements in the array, use enumerate
instead to access the element index and value:
fn main() {
let numbers = [4, 5, 7];
let result = numbers.iter().enumerate().filter_map(|(i, &n)| {
if i > 0 && n != numbers[i-1] + 1 {
Some(n)
} else {
None
}
});
println!("{:?}", result.collect::<Vec<i32>>());
}
If you only need to find the first such element, you can use find_map
instead of filter_map
:
fn main() {
let numbers = [4, 5, 7];
let result = numbers.iter().enumerate().find_map(|(i, &n)| {
if i > 0 && n != numbers[i-1] + 1 {
Some(n)
} else {
None
}
});
println!("{:?}", result);
}
Answered by Psidom on February 26, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP