Reputation: 3217
How do I create an empty mutable two dimensional array in Rust?
This is what I have tried so far:
let mut state[[u8 * 4] * 4];
This produces the error
error: expected one of `:`, `;`, `=`, or `@`, found `[`
--> src/main.rs:2:18
|
2 | let mut state[[u8 * 4] * 4];
| ^ expected one of `:`, `;`, `=`, or `@` here
Upvotes: 83
Views: 146963
Reputation: 14548
May use a type and get all the ergonomics that comes with it.
#[derive(Debug)]
struct SomeContextName {
x: u32,
y: u32,
}
fn main() {
let v = vec![
SomeContextName{x: 1, y: 1}, SomeContextName{x: 1, y: 2},
SomeContextName{x: 2, y: 1}, SomeContextName{x: 2, y: 2},
];
print!("v is {:#?}", v);
}
v is [ SomeContextName { x: 1, y: 1, }, SomeContextName { x: 1, y: 2, }, SomeContextName { x: 2, y: 1, }, SomeContextName { x: 2, y: 2, }, ]
Upvotes: 0
Reputation: 2390
with macro vec![] ..
let n = 18;
let mut grid = vec![vec![0; n]; n];
grid[0][0] = 1;
Upvotes: 1
Reputation: 1386
Editor's note: This answer predates Rust 1.0 and some of the concepts and syntax have changed. Other answers apply to Rust 1.0.
Do you want the contents of the array to be mutable or the variable that holds it? If you want mutable contents, does this work for you?
let state = [mut [mut 0u8, ..4], ..4];
If you want the variable to be mutable but not the contents, try this:
let mut state = [[0u8, ..4], ..4];
Does this help? I didn't actually compile this, so the syntax might be slightly off.
Upvotes: 32
Reputation: 3115
With explicit initialization
let directions: [[i32; 2]; 4] = [[-1, 0], [0, 1], [0, 1], [1, 0]]
With the same value
let directions: [[i32; 2]; 4] = [[0; 2]; 4];
Upvotes: 10
Reputation: 551
Another example of a two-dimensional string array:
fn main() {
let width = 2;
let height = 3;
let mut a: Vec<Vec<String>> = vec![vec![String::from(""); width]; height];
for i in 0..height {
for j in 0..width {
let s = format!("{}:{}", i + 1, j + 1);
a[i][j] = s;
}
}
println!("{:?}", a);
}
Output:
[
["1:1", "1:2"],
["2:1", "2:2"],
["3:1", "3:2"]
]
But I am not sure why we cannot use this form: a = [[String::from(""), 2], 3]
. I don't understand the difference between vec![]
and []
.
Upvotes: 4
Reputation: 121
Well, the question of how to create a vector is properly addressed above. Here is the code snippet to create a two-dimensional vector and then fill it with user input:
use std::io;
fn main(){
let width = 4;
let height = 4;
let mut array = vec![vec![0; width]; height];
for i in 0..4 {
let mut xstr = String::from("");
io::stdin().read_line(&mut xstr).ok().expect("read error");
array[i] = xstr
.split_whitespace()
.map(|s| s.parse().expect("parse error"))
.collect();
}
println!("{:?}", array)
}
Upvotes: 6
Reputation: 717
If you are open to installing a crate, the ndarray
can gracefully do it for you.
use ndarray::Array2;
let mut array = Array2::zeros((4, 3));
array[[1, 1]] = 7;
With some of the already existing answers, it is not possible to create an array using non-constant dimensions. There is no such problems with ndarray
. You can also effortlessly create dimensions of more than two dimensions.
You can find more details here and here.
Upvotes: 8
Reputation: 739
You can create a dynamically-sized 2D vector like this:
fn example(width: usize, height: usize) {
// Base 1d array
let mut grid_raw = vec![0; width * height];
// Vector of 'width' elements slices
let mut grid_base: Vec<_> = grid_raw.as_mut_slice().chunks_mut(width).collect();
// Final 2d array `&mut [&mut [_]]`
let grid = grid_base.as_mut_slice();
// Accessing data
grid[0][0] = 4;
}
Upvotes: 33
Reputation: 33036
You can also create a 2D array like this (using Vec
) if you don't have a known size at compile time:
let width = 4;
let height = 4;
let mut array = vec![vec![0; width]; height];
Use it like this:
array[2][2] = 5;
println!("{:?}", array);
Output:
0 0 0 0
0 0 0 0
0 0 5 0
0 0 0 0
Available since rust 1.0.0 https://doc.rust-lang.org/std/vec/struct.Vec.html
Upvotes: 25
Reputation: 5474
Initialization:
There are several approaches for 2D Array initialization:
Using constants for M (rows) & N (columns)
const M: usize = 2;
const N: usize = 4;
let mut grid = [[0 as u8; N] ; M];
Explicit declaration with type annotations
let mut grid: [[u8; 4]; 2] = [[0; 4]; 2];
Traversing:
The read-only traversing is as easy as:
for (i, row) in grid.iter().enumerate() {
for (j, col) in row.iter().enumerate() {
print!("{}", col);
}
println!()
}
or
for el in grid.iter().flat_map(|r| r.iter()) {
println!("{}", el);
}
Updating element(s):
for (i, row) in grid.iter_mut().enumerate() {
for (j, col) in row.iter_mut().enumerate() {
col = 1;
}
}
Upvotes: 16
Reputation: 12164
In Rust 1.0, the following works:
let mut state = [[0u8; 4]; 6];
state[0][1] = 42;
Note that the length of the interior segment is an integral part of the type. For example, you can reference (and pass) state
as follows:
let a: &[[u8; 4]] = &state;
but not without specifying the fixed length of the sub-array. If you need variable length sub-arrays you may need to do something like this:
let x: [Box<[u8]>; 3] = [
Box::new([1, 2, 3]),
Box::new([4]),
Box::new([5, 6])
];
let y: &[Box<[u8]>] = &x;
Upvotes: 98
Reputation: 51
Idiomatic C 2-dimensional arrays are declared using the same order of array sizes as used when accessing the array:
// Declaration
int array_2d[8][16]; // An 8 by 16 2D array
...
// Access
array_2d[0][1] = 5;
In Rust, the declaration sizes are flipped; to create an 8 by 16 2-dimensional array, the syntax is:
// Declaration
let mut array_2d: [[i32; 16]; 8];
...
// Access (same as idiomatic C. types for added explicitness)
array_2d[0_usize][1_usize] = 5;
Upvotes: 5