Erstellen eines Vektors von Nullen für eine bestimmte Größe

76

Ich möchte einen Vektor von Nullen mit einer bestimmten Größe initialisieren, die zur Laufzeit festgelegt wird.

In C wäre es wie:

int main(void)
{
    uint size = get_uchar();
    int A[size][size];
    memset(A, 0, size*size*sizeof(int));
}

Hier ist die Hilfsfunktion, die ich versucht habe, in Rust zu schreiben, aber ich denke, die Slicing-Syntax 0..sizebeleidigt den Compiler. Außerdem sieht es ausführlicher aus als die C-Version. Gibt es einen idiomatischeren Weg, dies zu tun?

fn zeros(size: u32) -> Vec<i32> {
    let mut zero_vec: Vec<i32> = Vec::with_capacity(size);
    for i in 0..size {
        zero_vec.push(0);
    }
    return zero_vec;
}

Ich schwöre, dass die alten Dokumente hier eine from_elem()Methode erklärt haben und keine der Permutationen der [0 ; size] Notation zu funktionieren scheint

Ich möchte dies letztendlich in einen Teilstring-Suchalgorithmus einfügen:

pub fn kmp(text: &str, pattern: &str) -> i64 {
    let mut shifts = zeros(pattern.len()+1);
}
elleciel
quelle

Antworten:

89

Um einen Vektor von Nullen (oder einen anderen konstanten Wert) einer bestimmten Länge zu initialisieren, können Sie das vec!Makro verwenden:

let len = 10;
let zero_vec = vec![0; len];

Trotzdem funktionierte Ihre Funktion nach nur wenigen Syntaxkorrekturen für mich:

fn zeros(size: u32) -> Vec<i32> {
    let mut zero_vec: Vec<i32> = Vec::with_capacity(size as usize);
    for i in 0..size {
        zero_vec.push(0);
    }
    return zero_vec;
}

uintist in Rust 1.0 nicht mehr vorhanden, sizemusste umgewandelt werden als usizeund die Typen für die Vektoren mussten übereinstimmen (geändert let mut zero_vec: Vec<i64>in let mut zero_vec: Vec<i32>.

anderspitman
quelle
4
Ich habe Rust auf 1.0 aktualisiert und let mut shifts = vec![0; pattern.len()];arbeite jetzt direkt ... Ups. Vorher hatte ich ein error: expected : , found .` ../search.rs:17 zero_vec.push (0); `was keinen Sinn ergab.
Elleciel
3
Ich war selbst dort. Als ich anfing, war es sehr schwer zu wissen, ob ich die Syntax falsch verwendet habe oder ob sich die Syntax seit der letzten Aktualisierung oder seit der Aktualisierung des von mir gelesenen Dokuments geändert hat. Ich bin wirklich froh, dass wir jetzt die Beta haben und freue mich auf 1.0. Übrigens verwenden Sie rustup.sh, um Rust zu aktualisieren? Wenn ja, möchten Sie vielleicht die neueste Version des Skripts erhalten, die jetzt die Beta anstelle von Nightlies erhält.
anderspitman
2
Aber deshalb mag ich die Sprache am meisten - die Community-Unterstützung ist wunderbar, keine Downvotes für meine Noob-Frage. :) Ja, ich habe das Neueste zusammengerollt rustup.sh. Vielen Dank! Jetzt muss ich nur noch den
Indexzugriff
Natürlich können Sie sich fragen, warum Sie überhaupt nach Antworten für eine so grundlegende Frage suchen müssten. Dies ist in den meisten anderen Sprachen intuitiver, z. B. in Sprachen, die beim Initialisieren eines Arrays / Vektors standardmäßig auf Null gesetzt sind.
Maarten Bodewes
Eine sehr einfache Frage, aber als ich dies tat, erhielt ich einen 2-Element-Vektor von 0 und 3, bei dem die Größe, auf die ich ihn initialisieren wollte, 3 war. Gibt es einige Kriterien, die dazu führen würden, dass sich die Initialisierung anders verhält?
Tedford
14

Hier ist ein anderer Weg, viel kürzer. Es funktioniert mit Rust 1.0:

fn zeros(size: u32) -> Vec<i32> {
    vec![0; size as usize]
}

fn main() {
    let vec = zeros(10);
    for i in vec.iter() {
        println!("{}", i)
    }
}
VRage
quelle
3
Wie unterscheidet sich dies vom letzten Teil der Antwort von @anders?
Shepmaster
10

Sie können auch die iter::repeatFunktion verwenden, die meiner Meinung nach "idiomatischer" ist (und für mich einfach besser aussieht):

use std::iter;

fn zeros(size: usize) -> Vec<i32> {
    iter::repeat(0).take(size).collect()
}
tckmn
quelle
Wird das als idiomatischer angesehen als die Verwendung von vec! direkt? Würde das schneller laufen?
anderspitman
@anders Keine Ahnung; Ich bin damit einverstanden, dass die vec!Version auch gut aussieht. Ich nehme an, es könnte nicht schaden, einige Benchmarks auszuprobieren, die ich machen könnte, wenn ich nach Hause komme.
Tckmn
Ja, ich frage mich jetzt, was die Implementierung von vec ist! ist. Ich werde sehen, ob ich etwas Zeit finde, mich ein wenig damit zu beschäftigen.
anderspitman
8
Die Verwendung des vec-Makros wird als idiomatischer angesehen. Es wurde speziell hinzugefügt, weil die Benutzer dies nicht wollten.
Steve Klabnik
1
Hinweis: ::<Vec<i32>>Ist überflüssig. Typinferenz kann dies automatisch herausfinden, da es sich um den Typ des Ausdrucks handeln muss. Sie können ihn also einfach .collect()hier verwenden.
Matthieu M.
3

Sie können die Größenänderung verwenden

let mut v = Vec::new();
let l = 42;
v.resize(l, 0u32);
lu_zero
quelle
5
vec!ist effizienter bei der Zuweisung von 0, da es verwendet RawVec::with_capacity_zeroed(), während .resize()Aufrufe, .extend_with()die einen komplexeren Wertgenerator verwenden. Für andere Werte verwenden beide, .extend_with()so dass der Nutzen ungefähr gleich ist.
Jocelyn