مقدمة: لماذا سؤال join في Rust شائع جدًا؟
إذا كنت قد انتقلت يومًا من Python أو JavaScript إلى Rust، فمن المحتمل أنك واجهت هذه اللحظة. تكتب كودًا جميلًا، لديك متجه من السلاسل النصية Vec<String>، وتحتاج فقط إلى دمجها بفاصلة. في Python كان سيكون ", ".join(my_list). في JavaScript — myArray.join(", "). أما في Rust... فتذهب إلى التوثيق وتجد أن طريقة join موجودة، لكنها ليست لـ Vec، بل لـ الشرائح (slice).
سؤال على Stack Overflow "What is the equivalent of the join operator over a vector of Strings?" حصد آلاف المشاهدات. وهذا ليس من قبيل الصدفة. في عام 2025، بينما يواصل Rust كسب قلوب مبرمجي الأنظمة ومطوري الويب، يصبح فهم كيفية دمج السلاسل النصية بشكل صحيح وفعال مهارة بالغة الأهمية.
في هذه المقالة، لن نقدم الإجابة فقط. سنستعرض جميع الطرق لدمج السلاسل النصية في Rust: من concat البسيط إلى join المتقدم مع فواصل مخصصة. ستتعرف على الطريقة التي تختارها لمهمتك ولماذا. هيا بنا!
الأساسيات: ما هو join ولماذا نحتاجه؟
تخيل أن لديك قائمة بأسماء المستخدمين: ["Alice", "Bob", "Charlie"]. تريد عرضها بالتنسيق: "Alice, Bob, Charlie". هذه هي عملية join — دمج عناصر المجموعة في سلسلة نصية واحدة باستخدام فاصل.
في Rust، لا توجد طريقة مدمجة join مباشرة لـ Vec<String>. لكن هناك طريقتان رئيسيتان تحلان هذه المشكلة:
- طريقة
joinللشرائح (slice) — الطريقة الأكثر مباشرة وفعالية. - طريقة
collectمع المكرر — أكثر وظيفية، لكنها أقل وضوحًا للمبتدئين.
دعنا نستعرض كل منهما مع أمثلة.
الطريقة رقم 1: slice.join() — الكلاسيكية
هذه هي الطريقة الأبسط والأكثر بديهية. في Rust، يتم تعريف طريقة join للسمة SliceConcatExt، والتي يتم تنفيذها لجميع الشرائح. نظرًا لأنه يمكن تحويل Vec بسهولة إلى شريحة (عبر &vec أو vec.as_slice())، يمكننا استخدامها مباشرة.
fn main() { let names = vec!["Alice".to_string(), "Bob".to_string(), "Charlie".to_string()]; // تحويل Vec<String> إلى &[String] واستدعاء join let joined = names.join(", "); println!("{}", joined); // الإخراج: Alice, Bob, Charlie}كيف يعمل هذا؟
تأخذ طريقة join فاصلًا (في حالتنا ", ") وتدرجه بين كل عنصر من عناصر الشريحة. لا تضيف الفاصل في البداية أو النهاية — فقط بين العناصر.
هام: join يُرجع String، وليس &str. هذا يعني أنه ينشئ سلسلة نصية جديدة، ناسخًا البيانات من جميع العناصر.
متى تستخدم slice.join()؟
- عندما يكون لديك
Vec<String>أو&[String] - عندما تحتاج إلى فاصل مخصص
- عندما تكون الأداء مهمًا — هذه هي الطريقة الأسرع
الطريقة رقم 2: iter().collect() — المنهج الوظيفي
إذا كنت تحب المكررات والأسلوب الوظيفي، ستعجبك هذه الطريقة. بدلاً من join، يمكنك استخدام collect مع النوع String:
fn main() { let names = vec!["Alice".to_string(), "Bob".to_string(), "Charlie".to_string()]; // استخدام المكرر و collect let joined: String = names.iter().map(|s| s.as_str()).collect::<Vec<&str>>().join(", "); println!("{}", joined); //