จะจับคู่สตริงกับตัวอักษรสตริงใน Rust ได้อย่างไร


205

ฉันพยายามที่จะหาวิธีจับคู่Stringในสนิม

ตอนแรกฉันพยายามจับคู่แบบนี้ แต่ฉันคิดว่า Rust ไม่สามารถส่งผ่านstd::string::Stringไปโดยปริยาย&strได้

fn main() {
    let stringthing = String::from("c");
    match stringthing {
        "a" => println!("0"),
        "b" => println!("1"),
        "c" => println!("2"),
    }
}

มีข้อผิดพลาด:

error[E0308]: mismatched types
 --> src/main.rs:4:9
  |
4 |         "a" => println!("0"),
  |         ^^^ expected struct `std::string::String`, found reference
  |
  = note: expected type `std::string::String`
             found type `&'static str`

ฉันพยายามสร้างStringวัตถุใหม่เนื่องจากฉันไม่สามารถหาฟังก์ชั่นเพื่อส่ง a Stringไป&strได้

fn main() {
    let stringthing = String::from("c");
    match stringthing {
        String::from("a") => println!("0"),
        String::from("b") => println!("1"),
        String::from("c") => println!("2"),
    }
}

สิ่งนี้ทำให้ฉันข้อผิดพลาดต่อไปนี้ 3 ครั้ง:

error[E0164]: `String::from` does not name a tuple variant or a tuple struct
 --> src/main.rs:4:9
  |
4 |         String::from("a") => return 0,
  |         ^^^^^^^^^^^^^^^^^ not a tuple variant or struct

จะจับคู่Strings ใน Rust ได้อย่างไร?


stringthing.as_str()อาจเป็นคำตอบที่ตรงไปตรงมาที่สุด ฉันไม่ชอบas_refเพราะมันเป็นเรื่องทั่วไปที่ไม่จำเป็นซึ่งจะนำไปสู่ข้อบกพร่องและไม่เป็นที่ชัดเจนจะไม่สมบูรณ์ชัดเจนว่าas_ref()เป็นไปได้&str, as_strเป็นเรื่องง่ายและชัดเจน
Zorf

@Zorf คุณพูดถูก คำตอบที่ได้รับการยอมรับเมื่อas_strยังไม่ได้อยู่ ฉันเปลี่ยนคำตอบที่ยอมรับ แต่ขอบคุณทุกคนที่ตอบคำถามนี้!
Jeroen

คำตอบ:


82

คุณสามารถทำสิ่งนี้:

match &stringthing[..] {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

นอกจากนี้ยังมีas_strวิธีการของสนิม 1.7.0:

match stringthing.as_str() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

190

as_sliceเลิกใช้แล้วคุณควรใช้คุณลักษณะstd::convert::AsRefแทน:

match stringthing.as_ref() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

โปรดทราบว่าคุณต้องจัดการกรณีและปัญหา catch-all อย่างชัดเจน


3
ใช้สนิม 1.4.0 หนึ่งสามารถใช้trim()ฟังก์ชั่น เพียงแค่ใช้as_ref()ไม่ตรงกับสตริง
futtetennista

1
ฉันคิดว่าการจับคู่ล้มเหลวเนื่องจากช่องว่างที่trim()ลบออก นี่เป็นการดีสำหรับการเลื่อนการจับคู่กับอินพุตของผู้ใช้
เจอราร์ดเซกซ์ตัน

1
มันไม่ทำงาน มันสามารถจับคู่ _ เท่านั้นหากฉันได้รับ String จาก read_line
ชายสวมหน้ากาก

ไม่ได้รู้มากเกี่ยวกับวิธีการจัดการสนิมประเภทที่แตกต่างกันของสตริง แต่ดูเหมือนว่าจะทำงานในตัวอย่างพื้นฐาน
tforgione


10

หมายเหตุจากบรรณาธิการ: คำตอบนี้เกี่ยวข้องกับรุ่นของสนิมก่อน 1.0 และไม่ทำงานในรุ่นสนิม 1.0

คุณสามารถจับคู่ในส่วนของสตริง

match stringthing.as_slice() {
    "a" => println!("0"),
    "b" => println!("1"),
    "c" => println!("2"),
    _ => println!("something else!"),
}

ดีกว่าที่จะใช้.as_ref()หรือ.as_str()ทั้งสองไม่ได้เป็นเจ้าของ
Abrar Khan

1

คุณสามารถลอง:

fn main() {
    let stringthing = String::from("c");
    match &*stringthing {
        "a" => println!("0"),
        "b" => println!("1"),
        "c" => println!("2"),
        _ => println!("else")
    }
}

2
มันอาจปรับปรุงประโยชน์ของคำตอบของคุณถ้าคุณอธิบายว่าอะไร&*stringthingและทำอะไร
Seth Difley
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.