Rust: Rust Arrays and Tuples

Last updated: 2026-08-26

Arrays and tuples are the most basic "fixed-size collections" in Rust—arrays store multiple values of the same type, while tuples can store multiple values of different types. They are both allocated on the stack and incur no runtime overhead.

In system programming, fixed-size collections mean a well-defined memory layout and predictable performance. The Rust compiler needs to know how much memory each variable occupies, and the sizes of arrays and tuples are fully determined at compile time.


1. What You'll Learn



2. The Story of a Financial Analyst

(1) The Problem: Storing Data in Disparate Variables

Alice is a financial analyst at the company and needs to store the monthly revenue data for the first half of 2026:

RUST
let jan = 120_000;  // Jan
let feb = 135_000;  // Feb
let mar = 128_000;  // Mar
let apr = 142_000;  // Apr
let may = 150_000;  // May
let jun = 165_000;  // Jun

// Want to calculate half-year total?
let sum = jan + feb + mar + apr + may + jun;  // Tedious and error-prone

Six months' worth of data is already a pain—what if you had to store 365 days' worth? Would you have to define 365 variables? Passing six variables to a function is already enough to drive you crazy. What's more, you can't use a loop to handle them.

(2) Solution for Rust Arrays

RUST
fn main() {
    // Half-year revenue: Jan ~ Jun 2026
    let revenue: [i32; 6] = [120_000, 135_000, 128_000, 142_000, 150_000, 165_000];

    // Total: one line
    let sum: i32 = revenue.iter().sum();
    println!("2026 H1 total revenue: {} yuan", sum);

    // Average
    let avg = sum as f64 / revenue.len() as f64;
    println!("Monthly average: {:.0} yuan", avg);

    // Print each month
    for (i, val) in revenue.iter().enumerate() {
        println!("Month {}: {} yuan", i + 1, val);
    }
}

Arrays store all data of the same type in a single variable—you can access it using indices, iterate through it using loops, pass it to functions, and use iterators to compute and aggregate data. Six lines of code replace 20 lines of scattered variables.



3. Arrays and Tuples

(1) Comparison of Concepts

100%
graph TB
    A[Rust fixed-size collections] --> B[Array [T; N]]
    A --> C[Tuple (T1, T2, ...)]
    B --> D[All elements same type]
    B --> E[Compile-time fixed length]
    B --> F[Index access: arr[i]]
    C --> G[Elements can differ in type]
    C --> H[Pattern destructuring]
    C --> I[Multiple return values]

(2) Arrays vs. Tuples

Dimension Array [T; N] Tuple (T1, T2, ...)
Element Type Must all be the same May be different
Length Fixed at compile time (N) Fixed at compile time (number of elements)
Access Method arr[index] tuple.field_index or Deconstruction
Use Cases Sets of data of the same type (e.g., monthly revenue) Combinations of heterogeneous data (e.g., return values and error codes)
Memory Contiguous memory block Contiguous memory block (may include alignment padding)
Generic Parameters [T; N] — Type + Length (T1, T2) — Type at each position
Out-of-Bounds Check Runtime panic N/A (field number is known at compile time)

(3) Quick Reference for Common Array Methods

Method Return Type Description
len() usize Return array length
get(i) Option<&T> Secure Index Access
get_mut(i) Option<&mut T> Secure Variable Access
iter() Iter<T> Back to Reference Iterators
contains(&val) bool Whether a value is included
sort() () In-place sorting (requires &mut)
map(f) Converted via .iter().map()
reverse() () In-place rotation (requires &mut)

(4) Selecting a Fixed-Length Set

Scenario Recommended Type Reason
Fixed number of elements of the same type [T; N] Array Stack allocation, zero overhead, type-safe
Heterogeneous Fixed Combinations (T1, T2, ...) Tuple Combinations of Different Types, Pattern Deconstruction
Functions with multiple return values Tuples Lightweight; no need to define structures
RGB/Coordinates Tuple Structure Has a type name, prevents name collisions
Large amounts of similar data Vec<T> Dynamic growth, heap allocation


4. Examples of Arrays and Tuples

▶ Example 1: Array Declaration, Access, and Iteration (Difficulty ⭐)

Output:

TEXT 📖 Display only
First month: 100
Third month: 300
Array length: 6
All values: 
<val> 

months[<index>] = <value>
Zeros array: <zeros>
RUST
// ============================================
// Arrays: declaration, indexing, and iteration
// ============================================

fn main() {
    // Type 1: Explicit type annotation
    let months: [i32; 6] = [100, 200, 300, 400, 500, 600];

    // Type 2: Type inference
    let zeros = [0; 5];  // [0, 0, 0, 0, 0], shorthand for [0, 0, 0, 0, 0]

    // Access by index (0-based)
    println!("First month: {}", months[0]);   // 100
    println!("Third month: {}", months[2]);   // 300

    // len() returns the array length
    println!("Array length: {}", months.len());  // 6

    // Iterate with a for loop
    print!("All values: ");
    for val in months {
        print!("{} ", val);
    }
    println!();

    // Iterate with index using .iter().enumerate()
    for (index, value) in months.iter().enumerate() {
        println!("months[{}] = {}", index, value);
    }

    // The shorthand `[val; N]` syntax
    println!("Zeros array: {:?}", zeros);
}

Output:

TEXT 📖 Display only
First month: 100
Third month: 300
Array length: 6
All values: 100 200 300 400 500 600
months[0] = 100
months[1] = 200
months[2] = 300
months[3] = 400
months[4] = 500
months[5] = 600
Zeros array: [0, 0, 0, 0, 0]

There are two ways to declare an array: [initial_value; length] is a convenient shorthand, and [type; length] is the full syntax. Use arr[i] to access elements by index, and for val in arr to iterate through the array. .iter().enumerate() lets you retrieve both the index and the value at the same time.


▶ Example 2: Array Index Out-of-Bounds and Safety Checks (Difficulty ⭐⭐)

Output:

TEXT 📖 Display only
scores[0] = 95
scores[1] = 87
scores[2] = 92
scores[5] = <scores[5]>
Safe get(0): <val>
Index 0 out of bounds
Safe get(5): <val>
Index 5 out of bounds -- safely handled!
scores.get(5) with default: <val>
RUST
// ============================================
// Array out-of-bounds: Rust panics at runtime
// ============================================

fn main() {
    let scores: [i32; 3] = [95, 87, 92];

    // Safe access: within bounds
    println!("scores[0] = {}", scores[0]);  // OK
    println!("scores[1] = {}", scores[1]);  // OK
    println!("scores[2] = {}", scores[2]);  // OK

    // Out of bounds: THIS WILL PANIC at runtime
    // Uncomment the line below to see the error:
    // println!("scores[5] = {}", scores[5]);
    //
    // Output:
    // thread 'main' panicked at src/main.rs:XX:YY:
    // index out of bounds: the len is 3 but the index is 5

    // Safe alternative: use .get() which returns Option<&T>
    let first = scores.get(0);   // Some(&95)
    let invalid = scores.get(5); // None

    match first {
        Some(val) => println!("Safe get(0): {}", val),
        None => println!("Index 0 out of bounds"),
    }

    match invalid {
        Some(val) => println!("Safe get(5): {}", val),
        None => println!("Index 5 out of bounds -- safely handled!"),
    }

    // Using .get() with a default value
    let val = scores.get(5).copied().unwrap_or(-1);
    println!("scores.get(5) with default: {}", val);  // -1
}

Output:

TEXT 📖 Display only
scores[0] = 95
scores[1] = 87
scores[2] = 92
Safe get(0): 95
Index 5 out of bounds -- safely handled!
scores.get(5) with default: -1

Using arr[i] directly will cause a runtime panic (crash) if the index is out of bounds. The safe way is to use the .get() method—it returns Option<&T>, allowing you to gracefully handle out-of-bounds conditions using match or unwrap_or instead of causing an immediate crash.


▶ Example 3: Creating and Unpacking Tuples, and Function Return Values (Difficulty ⭐⭐)

Output:

TEXT 📖 Display only
Name: <person.0>
Age: <person.1>
Active: <person.2>
Destructured -- <name> is <age> years old, active: <active>
Q1 -- Sum: <count>, Count: <avg>, Avg: <sum>
Nested: <nested>, inner: <(nested.1).1>
Single-element tuple: <single>
Not a tuple: <not_tuple>
RUST
// ============================================
// Tuples: creation, destructuring, and return values
// ============================================

// A function that returns a tuple: (sum, count, average)
fn analyze_sales(sales: &[i32]) -> (i32, usize, f64) {
    let sum: i32 = sales.iter().sum();
    let count = sales.len();
    let avg = sum as f64 / count as f64;
    (sum, count, avg)  // return as a tuple
}

fn main() {
    // Tuple with different types: (name, age, active)
    let person: (&str, u8, bool) = ("Alice", 30, true);

    // Access by field index
    println!("Name: {}", person.0);
    println!("Age: {}", person.1);
    println!("Active: {}", person.2);

    // Destructuring: unpack tuple into variables
    let (name, age, active) = person;
    println!("Destructured -- {} is {} years old, active: {}", name, age, active);

    // Tuple as function return value
    let q1_sales = [120_000, 135_000, 128_000];  // Jan, Feb, Mar
    let (sum, count, avg) = analyze_sales(&q1_sales);
    println!("Q1 -- Sum: {}, Count: {}, Avg: {:.0}", sum, count, avg);

    // Nested tuples
    let nested = (1, (2.5, "hello"), true);
    println!("Nested: {:?}, inner: {}", nested, (nested.1).1);

    // Single-element tuple: note the trailing comma!
    let single = (42,);     // tuple with one element
    let not_tuple = (42);   // just a parenthesized integer
    println!("Single-element tuple: {:?}", single);
    println!("Not a tuple: {}", not_tuple);
}

Output:

TEXT 📖 Display only
Name: Alice
Age: 30
Active: true
Destructured -- Alice is 30 years old, active: true
Q1 -- Sum: 383000, Count: 3, Avg: 127667
Nested: (1, (2.5, "hello"), true), inner: hello
Single-element tuple: (42,)
Not a tuple: 42

Tuples can store values of different types. You can access their fields using .0, .1, and .2, or use the let (a, b, c) = tuple pattern for destructuring. Tuples are particularly well-suited for functions that return multiple values—without the need to define a struct. Note that a single-element tuple must be enclosed in a comma (42,).


▶ Example 4: Iterating Through Arrays and Common Methods (Difficulty ⭐⭐)

Output:

TEXT 📖 Display only
All revenues: 
<r> 

With .iter(): 
<r> 


Monthly report:
  <month_names[i]>: <r> yuan

Growth rate:
  <month_names[i]> -> <growth>: <month_names[i - 1]>%

Summary:
  Total:     <revenue.iter().sum::<i32>()>
  Max:       <revenue.iter().max().unwrap()>
  Min:       <revenue.iter().min().unwrap()>
  Count > 140k: <revenue.iter().filter(|&&r| r > 140_000).count()>
RUST
// ============================================
// Array iteration and common methods
// ============================================

fn main() {
    let revenue: [i32; 6] = [120_000, 135_000, 128_000, 142_000, 150_000, 165_000];
    let month_names = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"];

    // Method 1: for-in (by value -- copies each element for i32)
    print!("All revenues: ");
    for r in revenue {
        print!("{} ", r);
    }
    println!();

    // Method 2: .iter() (by reference)
    print!("With .iter(): ");
    for r in revenue.iter() {
        print!("{} ", r);
    }
    println!();

    // Method 3: .iter().enumerate() (index + value)
    println!("\nMonthly report:");
    for (i, r) in revenue.iter().enumerate() {
        println!("  {}: {} yuan", month_names[i], r);
    }

    // Method 4: for i in 0..len (C-style index)
    println!("\nGrowth rate:");
    for i in 1..revenue.len() {
        let growth = (revenue[i] - revenue[i - 1]) as f64 / revenue[i - 1] as f64 * 100.0;
        println!("  {} -> {}: {:.1}%", month_names[i - 1], month_names[i], growth);
    }

    // Common array methods
    println!("\nSummary:");
    println!("  Total:     {}", revenue.iter().sum::<i32>());
    println!("  Max:       {}", revenue.iter().max().unwrap());
    println!("  Min:       {}", revenue.iter().min().unwrap());
    println!("  Count > 140k: {}", revenue.iter().filter(|&&r| r > 140_000).count());
}

Output:

TEXT 📖 Display only
All revenues: 120000 135000 128000 142000 150000 165000
With .iter(): 120000 135000 128000 142000 150000 165000

Monthly report:
  Jan: 120000 yuan
  Feb: 135000 yuan
  Mar: 128000 yuan
  Apr: 142000 yuan
  May: 150000 yuan
  Jun: 165000 yuan

Growth rate:
  Jan -> Feb: 12.5%
  Feb -> Mar: -5.2%
  Mar -> Apr: 10.9%
  Apr -> May: 5.6%
  May -> Jun: 10.0%

Summary:
  Total:     840000
  Max:       165000
  Min:       120000
  Count > 140k: 3

There are several ways to iterate over an array: for val in arr (value copying), arr.iter() (by reference), .enumerate() (indexed), and C-style indexed loops. Arrays also provide a rich set of iterator methods, such as .sum(), .max(), .min(), and .filter().


▶ Example 5: Comprehensive Exercise—Student Grade Statistics (Difficulty ⭐⭐⭐)

Output:

TEXT 📖 Display only
=== Student Report Card ===
Name         Sub1   Sub2   Sub3  Average  Level
<"-".repeat(44)>
<name> <scores[0]> <scores[1]> <scores[2]> <avg> <grade>
<"-".repeat(44)>
Class-wide Statistics: Lowest=<overall_max>, Highest=<overall_avg>, Average=<overall_min>, >=Average: <above_count> people

RUST
// ============================================
// Comprehensive Example: Array + Tuple + Iterators in Practice
// ============================================

fn analyze(scores: &[i32]) -> (i32, i32, f64, i32) {
    let min = *scores.iter().min().unwrap_or(&0);
    let max = *scores.iter().max().unwrap_or(&0);
    let sum: i32 = scores.iter().sum();
    let avg = if scores.is_empty() { 0.0 } else { sum as f64 / scores.len() as f64 };
    let above_avg = scores.iter().filter(|&&s| s as f64 >= avg).count() as i32;
    (min, max, avg, above_avg)
}

fn classify(score: i32) -> &'static str {
    match score {
        90..=100 => "A",
        80..=89  => "B",
        70..=79  => "C",
        60..=69  => "D",
        _        => "F",
    }
}

fn main() {
    let students = [
        ("Alice",   [95, 88, 92]),
        ("Bob",     [72, 65, 58]),
        ("Charlie", [85, 90, 78]),
        ("David",   [60, 55, 70]),
    ];

    println!("=== Student Report Card ===");
    println!("{:<10} {:>6} {:>6} {:>6} {:>8} {:>6}", "Name", "Sub1", "Sub2", "Sub3", "Average", "Level");
    println!("{}", "-".repeat(44));

    let mut all_scores: Vec<i32> = Vec::new();

    for (name, scores) in &students {
        let (min, max, avg, above) = analyze(scores);
        let grade = classify(avg as i32);
        println!("{:<10} {:>6} {:>6} {:>6} {:>8.1} {:>6}",
            name, scores[0], scores[1], scores[2], avg, grade);
        all_scores.extend(scores.iter());
    }

    let (overall_min, overall_max, overall_avg, above_count) = analyze(&all_scores);
    println!("{}", "-".repeat(44));
    println!("Class-wide Statistics: Lowest={}, Highest={}, Average={:.1}, >=Average: {} people",
        overall_min, overall_max, overall_avg, above_count);

    let subject_avgs: [f64; 3] = [
        students.iter().map(|(_, s)| s[0] as f64).sum::<f64>() / students.len() as f64,
        students.iter().map(|(_, s)| s[1] as f64).sum::<f64>() / students.len() as f64,
        students.iter().map(|(_, s)| s[2] as f64).sum::<f64>() / students.len() as f64,
    ];
    println!("\nSubject Average: Sub1={:.1}, Sub2={:.1}, Sub3={:.1}",
        subject_avgs[0], subject_avgs[1], subject_avgs[2]);
}

Output:

TEXT 📖 Display only
=== Student Report Card ===
Name         Sub1     Sub2     Sub3     Average    Level
--------------------------------------------
Alice         95      88      92     91.7      A
Bob           72      65      58     65.0      D
Charlie       85      90      78     84.3      B
David         60      55      70     61.7      D
--------------------------------------------
Class-wide Statistics: Lowest=55, Highest=95, Average=76.7, >=Average: 6 people

Subject Average: Sub1=78.0, Sub2=74.5, Sub3=74.5

This example combines the use of arrays and tuples: [i32; 3] stores the scores for each student in three subjects; the tuple (&str, [i32; 3]) combines names and scores; analyze returns the tuple (min, max, avg, count); and [f64; 3] stores the average score for each subject.


❓ FAQ

Q What is the difference between an array [u8; 3] and a slice &[u8]?
A The size of an array is fixed at compile time and allocated on the stack; a slice is a view of an array (pointer + length) that can point to a portion of the array.
Q What is the maximum number of elements a tuple can have?
A Theoretically, up to 12 elements (the standard library implements traits for tuples with up to 12 elements). However, if you have more than 4 or 5 fields, it is recommended to use a struct.
Q Why doesn’t the compiler report an error when my array goes out of bounds, but it panics at runtime?
A The compiler can only check for out-of-bounds accesses that can be determined at compile time (such as arr[100] where the array length is also a constant). Dynamic indexing (such as arr[i] where i comes from user input) can only be checked at runtime.
Q Both tuples and structs are used to "group multiple values"—when should you use which one?
A Tuples are suitable for temporary situations where fields don’t have semantic names (such as multiple return values); structs are suitable for data where fields have clear meanings and need to be reused.
Q [0; 5] Does this syntax work for all types?
A The element type must implement the Copy trait.

📖 Summary


📝 Exercises

  1. Difficulty ⭐: Declare a [f64; 7] array of length 7 to store the highest temperatures (in degrees Celsius) for each of the 7 days of the week. Use a loop to find the highest and lowest temperatures.
  2. Difficulty ⭐⭐: Write a function fn stats(arr: &[i32]) -> (i32, i32, f64) that returns (the minimum, maximum, and average). Test it in the main function using [10, 3, 7, 1, 9, 4].
  3. Difficulty ⭐⭐⭐: Define an array to store the students' scores [85, 92, 78, 90, 88]. Manually implement a function fn rank_scores(scores: &[i32]) -> Vec<(usize, i32, &str)> that returns a list of sorted tuples (rank, score, grade) (Grading rules: >=90 is "A", >=80 is "B", >=70 is "C", and all others are "D").
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏