I would like to know if it is possible to get all the indexes that fulfill a condition in a rust vector datatype. I know the trait operator provides a method to find the first element that does it:
let test=vec![1,0,0,1,1];
let index = test.iter().position(|&r| r == 1);
println!("{}",index) //0
However, I would be interested in obtaining all the indexes that are equal to 1 in the test vec.
let test=vec![1,0,0,1,1];
let indexes = //Some Code
println!("{:?}",indexes) //0,3,4
What should I do?
Use enumerate():
let test = vec![1, 0, 0, 1, 1];
let indices = test
.iter()
.enumerate()
.filter(|(_, &r)| r == 1)
.map(|(index, _)| index)
.collect::<Vec<_>>();
dbg!(indices); // 0, 3, 4
Playground.
You can also combine filter() and map(), although I think the former version is cleaner:
let indices = test
.iter()
.enumerate()
.filter_map(|(index, &r)| if r == 1 { Some(index) } else { None })
.collect::<Vec<_>>();
Or
let indices = test
.iter()
.enumerate()
.filter_map(|(index, &r)| (r == 1).then(|| index))
.collect::<Vec<_>>();
Related
How to split a vector
let v: Vec<u8>; // vector with size x
into a vector of vectors of maxsize n? Pseudocode:
let n: usize = 1024;
let chunks_list: Vec<Vec<u8>> = chunks(v, n);
or using slices (to avoid copying):
let v: &[u8];
let chunks_list: Vec<&[u8]> = chunks(v, n);
Rust slices already contain the necessary method for that: chunks.
Starting from this:
let src: Vec<u8> = vec![1, 2, 3, 4, 5];
you can get a vector of slices (no copy):
let dst: Vec<&[u8]> = src.chunks(3).collect();
or a vector of vectors (slower, heavier):
let dst: Vec<Vec<u8>> = src.chunks(3).map(|s| s.into()).collect();
playground
There is a method already existing for slices:
pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T>
Returns an iterator over chunk_size elements of the slice at a time, starting at the beginning of the slice.
The chunks are slices and do not overlap. If chunk_size does not divide the length of the slice, then the last chunk will not have length chunk_size.
There is also chunks_mut for mutability as well as chunks_exact and chunks_exact_mut if the last chunk has to respect the size n, along with the unsafe as_chunks_unchecked in case we assume there is no remainder, see below example:
fn main() {
let v: [u8; 5] = *b"lorem";
let n = 2;
let chunks = v.chunks(n);
let chunks_list: Vec<&[u8]> = chunks.collect();
println!("{:?}", chunks_list);
}
Using a slice instead of vectors has some benefits, notably avoiding the overhead of copying.
If it's required to take a Vec and split it into multiple Vecs, I'd use Itertools::chunks. This takes an iterator and returns an iterator of iterators. You can then choose to collect both the inner and outer iterators into Vecs:
use itertools::Itertools; // 0.10.0
fn main() {
let v = vec![String::from("A"), String::from("B"), String::from("C")];
let x: Vec<Vec<String>> = v.into_iter().chunks(2).into_iter().map(|c| c.collect()).collect();
eprintln!("{:?}", x);
}
[["A", "B"], ["C"]]
This has the benefit of taking ownership of each value in the original vector. No data needs to be copied, but it does need to be moved. If you can use slices instead, it's much better to use slice::chunks.
Here is one approach:
use std::{usize, vec};
fn chunks(data: Vec<u8>, chunk_size: usize) -> Vec<Vec<u8>> {
let mut results = vec![];
let mut current = vec![];
for i in data {
if current.len() >= chunk_size {
results.push(current);
current = vec![];
}
current.push(i);
}
results.push(current);
return results;
}
fn main() {
let v: Vec<u8> = (1..100).collect();
let n: usize = 24;
let chunks_list = chunks(v, n);
println!("{:#?}", chunks_list);
}
I'm trying to complete the activity at the bottom of this page, where I need to print the index of each element as well as the value. I'm starting from the code
use std::fmt; // Import the `fmt` module.
// Define a structure named `List` containing a `Vec`.
struct List(Vec<i32>);
impl fmt::Display for List {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Extract the value using tuple indexing
// and create a reference to `vec`.
let vec = &self.0;
write!(f, "[")?;
// Iterate over `vec` in `v` while enumerating the iteration
// count in `count`.
for (count, v) in vec.iter().enumerate() {
// For every element except the first, add a comma.
// Use the ? operator, or try!, to return on errors.
if count != 0 { write!(f, ", ")?; }
write!(f, "{}", v)?;
}
// Close the opened bracket and return a fmt::Result value
write!(f, "]")
}
}
fn main() {
let v = List(vec![1, 2, 3]);
println!("{}", v);
}
I'm brand new to coding and I'm learning Rust by working my way through the Rust docs and Rust by Example. I'm totally stuck on this.
In the book you can see this line:
for (count, v) in vec.iter().enumerate()
If you look at the documentation, you can see a lot of useful functions for Iterator and enumerate's description states:
Creates an iterator which gives the current iteration count as well as the next value.
The iterator returned yields pairs (i, val), where i is the current index of iteration and val is the value returned by the iterator.
enumerate() keeps its count as a usize. If you want to count by a different sized integer, the zip function provides similar functionality.
With this, you have the index of each element in your vector. The simple way to do what you want is to use count:
write!(f, "{}: {}", count, v)?;
This is a simple example to print the index and value of a vector:
fn main() {
let vec1 = vec![1, 2, 3, 4, 5];
println!("length is {}", vec1.len());
for x in 0..vec1.len() {
println!("{} {}", x, vec1[x]);
}
}
This program output is -
length is 5
0 1
1 2
2 3
3 4
4 5
I have the following function, which takes a vector as argument and returns a vector of its pairs of elements:
fn to_pairs(flat: Vec<u64>) -> Vec<(u64, u64)> {
assert!(flat.len() % 2 == 0);
let mut pairs = Vec::new();
pairs.reserve(flat.len() / 2);
for pair in flat.chunks(2) {
assert!(pair.len() == 2);
pairs.push((pair.get(0).unwrap().clone(), pair.get(1).unwrap().clone()));
}
pairs
}
I want consume the vector flat so I don't have to clone its elements when constructing the pair.
Is it possible to do so without reimplementing a variation of Vec::chunks() myself?
I want consume the vector flat so I don't have to clone its elements when constructing the pair.
Convert the input Vec into an iterator, then take two things from the iterator at a time. Essentially, you want the same thing as processing a Range (an iterator) in chunks:
fn to_pairs<T>(flat: Vec<T>) -> Vec<(T, T)> {
let len = flat.len();
assert!(len % 2 == 0);
let mut pairs = Vec::with_capacity(len / 2);
let mut input = flat.into_iter().peekable();
while input.peek().is_some() {
match (input.next(), input.next()) {
(Some(a), Some(b)) => pairs.push((a, b)),
_ => unreachable!("Cannot have an odd number of values"),
}
}
pairs
}
fn main() {
assert_eq!(vec![(1,2), (3,4)], to_pairs(vec![1,2,3,4]));
assert_eq!(vec![(true,true), (false,false)], to_pairs(vec![true,true,false,false]));
}
The assert!(len % 2 == 0); is quite important here, as Iterator makes no guarantees about what happens after the first time next returns None. Since we call next twice without checking the first value, we could be triggering that case. In other cases, you'd want to use fuse.
As pointed out by Kha, you could simplify the while loop a bit:
let mut input = flat.into_iter();
while let (Some(a), Some(b)) = (input.next(), input.next()) {
pairs.push((a, b));
}
I'm trying to write some code in a functional paradigm for practice. There is one case I'm having some problems wrapping my head around. I am trying to create an array of 5 unique integers from 1, 100. I have been able to solve this without using functional programming:
let uniqueArray = [];
while (uniqueArray.length< 5) {
const newNumber = getRandom1to100();
if (uniqueArray.indexOf(newNumber) < 0) {
uniqueArray.push(newNumber)
}
}
I have access to lodash so I can use that. I was thinking along the lines of:
const uniqueArray = [
getRandom1to100(),
getRandom1to100(),
getRandom1to100(),
getRandom1to100(),
getRandom1to100()
].map((currentVal, index, array) => {
return array.indexOf(currentVal) > -1 ? getRandom1to100 : currentVal;
});
But this obviously wouldn't work because it will always return true because the index is going to be in the array (with more work I could remove that defect) but more importantly it doesn't check for a second time that all values are unique. However, I'm not quite sure how to functionaly mimic a while loop.
Here's an example in OCaml, the key point is that you use accumulators and recursion.
let make () =
Random.self_init ();
let rec make_list prev current max accum =
let number = Random.int 100 in
if current = max then accum
else begin
if number <> prev
then (number + prev) :: make_list number (current + 1) max accum
else accum
end
in
make_list 0 0 5 [] |> Array.of_list
This won't guarantee that the array will be unique, since its only checking by the previous. You could fix that by hiding a hashtable in the closure between make and make_list and doing a constant time lookup.
Here is a stream-based Python approach.
Python's version of a lazy stream is a generator. They can be produced in various ways, including by something which looks like a function definition but uses the key word yield rather than return. For example:
import random
def randNums(a,b):
while True:
yield random.randint(a,b)
Normally generators are used in for-loops but this last generator has an infinite loop hence would hang if you try to iterate over it. Instead, you can use the built-in function next() to get the next item in the string. It is convenient to write a function which works something like Haskell's take:
def take(n,stream):
items = []
for i in range(n):
try:
items.append(next(stream))
except StopIteration:
return items
return items
In Python StopIteration is raised when a generator is exhausted. If this happens before n items, this code just returns however much has been generated, so perhaps I should call it takeAtMost. If you ditch the error-handling then it will crash if there are not enough items -- which maybe you want. In any event, this is used like:
>>> s = randNums(1,10)
>>> take(5,s)
[6, 6, 8, 7, 2]
of course, this allows for repeats.
To make things unique (and to do so in a functional way) we can write a function which takes a stream as input and returns a stream consisting of unique items as output:
def unique(stream):
def f(s):
items = set()
while True:
try:
x = next(s)
if not x in items:
items.add(x)
yield x
except StopIteration:
raise StopIteration
return f(stream)
this creates an stream in a closure that contains a set which can keep track of items that have been seen, only yielding items which are unique. Here I am passing on any StopIteration exception. If the underlying generator has no more elements then there are no more unique elements. I am not 100% sure if I need to explicitly pass on the exception -- (it might happen automatically) but it seems clean to do so.
Used like this:
>>> take(5,unique(randNums(1,10)))
[7, 2, 5, 1, 6]
take(10,unique(randNums(1,10))) will yield a random permutation of 1-10. take(11,unique(randNums(1,10))) will never terminate.
This is a very good question. It's actually quite common. It's even sometimes asked as an interview question.
Here's my solution to generating 5 integers from 0 to 100.
let rec take lst n =
if n = 0 then []
else
match lst with
| [] -> []
| x :: xs -> x :: take xs (n-1)
let shuffle d =
let nd = List.map (fun c -> (Random.bits (), c)) d in
let sond = List.sort compare nd in
List.map snd sond
let rec range a b =
if a >= b then []
else a :: range (a+1) b;;
let _ =
print_endline
(String.concat "\t" ("5 random integers:" :: List.map string_of_int (take (shuffle (range 0 101)) 5)))
How's this:
const addUnique = (ar) => {
const el = getRandom1to100();
return ar.includes(el) ? ar : ar.concat([el])
}
const uniqueArray = (numberOfElements, baseArray) => {
if (numberOfElements < baseArray.length) throw 'invalid input'
return baseArray.length === numberOfElements ? baseArray : uniqueArray(numberOfElements, addUnique(baseArray))
}
const myArray = uniqueArray(5, [])
This question is related to this previous thread.
I followed Tomas's suggestion using this piece code, and all works fine:
let GetSameColorNeighs (grid:Option<Ball>[,], row, col, color:Color) =
let rec loop (row, col) = seq {
if not (row < 0 || col < 0 || row > MaxLineNumber - 1
|| col > BallsPerLine - 1) then
let ball = grid.[row,col]
match ball with
| Some(ball) ->
if (!ball.visited = false || not <| ball.color.Equals(color)) then
// Not sure what you want here - yield items using 'yield'?
// [row , col]
else
ball.visited := true
yield row, col // Add single item to results
yield! loop(row + 1, col + 1) // Add all generated to results
yield! loop(row - 1, col - 1) // -- || --
| None -> () }
loop(row, col) |> Seq.toList
The code above iterate through an array 2d of "balls" and return a list of index of adjacent balls with the same color.
Now I have to modify the function in way that it returns also a boolean indicating if at least one ball of the list satisfy a certain condition. I changed the code this way but seems that I can't assign a mutable value inside that code:
let GetSameColorNeighs (grid:Option<Ball>[,], row, col, color:Color) : List<int * int> * bool =
let mutable b : bool = false
let rec loop (row, col) = seq {
if not (row < 0 || col < 0 || row > MaxLineNumber - 1
|| col > BallsPerLine - 1) then
let ball = grid.[row,col]
match ball with
| Some(ball) ->
if (ball.visited = true || not <| ball.color.Equals(color)) then
()
else
//HERE's THE PROBLEM
if (ball_satisfy_a_certain_condition) then
b <- true
ball.visited := true
yield row, col // Add single item to results
yield! loop(row + 1, col + 1) // Add all generated to results
yield! loop(row - 1, col - 1) // -- || --
| None -> () }
loop(row, col) |> Seq.toList, b
It seems that a mutable variable can't be acquired by a closure (I don't know what it means).
So I have 2 questions:
why is the above assignment to a mutable variable wrong?
How should I refactor my code to achieve this goal?
In short, you have to use ref variables instead of mutable variables.
While mutable variables are allocated on the stack, ref variables are heap-based. After each time your loop function is invoked, mutable values are wiped out when ref values are still there. Therefore, only ref values are valid to return in GetSameColorNeighs.
This question has been asked many times here. See The mutable variable 'i' is used in an invalid way.? and this blog post for more in-depth discussion.