Sw

Switch في R

1 تمرين

نبذة عن Switch

يمكن أن تكون الدالة switch() بديلًا موجزًا عن تتابع طويل من اختبارات if ... else if. وغالبًا ما يكون المتغير الذي يتم التبديل عليه من النوع سلسلة نصية، وفي هذه الحالة يمكن حذف علامات الاقتباس من المحدِّد.

star <- function(type) {
  switch(type,
    M = , # will "fall through" if no value given
    K = "red dwarf",
    G = "Earth-like",
    "bigger star" # only correct for O,B,A,F
  )
}

> star("M")
[1] "red dwarf"

لاحظ أن الخيارات لن تنتقل إلى ما بعدها إلا إذا تُركت القيمة فارغة، كما في M في المثال أعلاه. ولا حاجة إلى تضمين عبارات break كما هو الحال في بعض اللغات الأخرى.

يمكن أن تكون القيمة الأخيرة قيمة افتراضية، كما هنا، أو استدعاءً لـ stop() لإطلاق خطأ إذا كان القصد أن تغطي الشروط كل الحالات. أما التبديل على عدد صحيح فمختلف قليلًا: في هذه الحالة تكون القيمة الافتراضية دائمًا NULL (وسيُتناول ذلك في مفهوم العدم).

الدوال في dplyr

إن switch في R الأساسية محدودة جدًا: فهي لا تُجري إلا مطابقة تامة مع مدخل واحد. بدا هذا معقولًا عند إصدار R لأول مرة عام 1993، لكنه يحتاج إلى تحسين للاستخدام الحديث.

Note

كما ذُكر في مفهوم الشروط، فإن مجموعة الحزم tidyverse مصمَّمة لتكمّل وظائف R الأساسية (وأحيانًا لتحل محلها) دون التأثير على التوافق مع الإصدارات السابقة.

تتميز حزم tidyverse أيضًا بتوثيق حديث ممتاز، لذا فإن اتباع الروابط أدناه سيمنحك تفاصيل أكثر.

يمكن إدخال حزمة dplyr إلى النطاق بإضافة library(dplyr) (للحزمة الواحدة) أو library(tidyverse) (للمجموعة كاملة) إلى أعلى الكود الخاص بك.

توفّر مكتبة dplyr دالتين إضافيتين متعلقتين بـ switch.

الدالتان recode_values و replace_values

تسمح هاتان الدالتان المرتبطتان بإجراء تحويل على المتجهات يشبه switch، إذ تربطان القيم القديمة بقيم جديدة.

والفرق الأساسي بينهما هو أن recode_values() تُنشئ متجهًا جديدًا بالكامل، بينما تسمح replace_values() بتحديثات جزئية لمتجه موجود.

تبقى المطابقة تامة، لكن:

  • يمكن أن تكون الخيارات على اليسار متجهات، ويُعد المدخل مطابقًا إذا طابق أي عنصر.
  • تُربط الخيارات على اليسار بالنتائج على اليمين بعلامة التلدة ~ بدلًا من =.
  • يمكن مطابقة القيم المفقودة NA صراحةً (وسيُتناول ذلك في مفهوم العدم).
  • ويمكن تحديد قيمة افتراضية في جميع الحالات.
library(dplyr)

x <- c("a", "b", "a", "d", "b", NA, "c", "e", "z")
recode_values(
  x,
  "a" ~ 1,
  "b" ~ 2,
  "c" ~ 3,
  c("d", "e") ~ 4, # either "d' or "e" will match
  NA ~ 0,          # matches missing values
  default = 100   # note the different syntax for the default
)
#> [1]   1   2   1   4   2   0   3   4 100
Note

قد تجد نصائح على الإنترنت عن استخدام الدالة case_match() كبديل متجهي لـ Conditionals.

تم إهمال هذه الدالة في الإصدار 1.2.0 من dplyr (فبراير 2026). وسيؤدي أي محاولة لاستخدامها الآن إلى رسالة تحذير تنصح باستخدام recode_values() بدلًا منها.

الدالة case_when

تنقل case_when صياغة case_match خطوة أبعد، إذ تسمح بأي تعبير منطقي على يسار ~.

لا يُمرَّر متجه الإدخال (x في المثال أدناه) كوسيط، بل يكفي أن يكون معرَّفًا مسبقًا.

x <- 1:10
case_when(
  x < 3 ~ "low",
  between(x, 3, 5) ~ "mid",
  between(x, 6, 8) ~ "high",
  .default = "what?"
)
#>  [1] "low"   "low"   "mid"   "mid"   "mid"   "high"  "high"  "high"  "what?" "what?"

الدالة between() جزء من dplyr أيضًا.

سبق أن تناولنا دوال السلاسل النصية، وسيكون التعبيرات النمطية موضوع مفهوم لاحق. وهذه تتكامل جيدًا مع case_when.

library(stringr)

tracks <- "R C Python C# Elixir C++ Odin" |> str_split_1(" ")
tracks
#> [1] "R"      "C"      "Python" "C#"     "Elixir" "C++"    "Odin"  

case_when(
  str_starts(tracks, "C") ~ "C-like",
  str_starts(tracks, "[AEIOU]") ~ "vowel",
  .default = "other"
)
#> [1] "other"  "C-like" "other"  "C-like" "vowel"  "C-like" "vowel"
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة

تعلّم Switch