يمكن لدالة 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 كما هو الحال في بعض اللغات الأخرى.
عند التبديل على أنواع character، تكون القيمة الأخيرة هي القيمة الافتراضية، كما هنا. أما أنواع الأعداد الصحيحة فلا يمكن إعطاؤها قيمة افتراضية.
dplyr
إن دالة switch في R الأساسية محدودة جدًا: فهي لا تُجري إلا مطابقة تامة مع مدخل واحد. بدا ذلك معقولًا عند إصدار R الأول عام 1993، لكنه يحتاج إلى تحسين للاستخدام الحديث.
كما ذُكر في مفهوم Conditionals، صُمّمت مجموعة الحزم tidyverse لتكمّل وظائف R الأساسية (وأحيانًا لتحلّ محلها) دون التأثير على التوافق مع الإصدارات السابقة.
يمكن إحضار حزمة dplyr إلى النطاق بإضافة library(dplyr) (للحزمة الواحدة) أو library(tidyverse) (لكل المجموعة) إلى أعلى الكود.
توفّر مكتبة dplyr دالتين إضافيتين مرتبطتين بـswitch.
recode_values وreplace_values
تسمح هاتان الدالتان المرتبطتان بإجراء تحويل شبيه بالتبديل على مستوى المتجهات، يربط القيم القديمة بقيم جديدة.
الفرق الأساسي بينهما هو أن recode_values() تُنشئ متجهًا جديدًا بالكامل، بينما تسمح replace_values() بتحديثات جزئية لمتجه موجود.
المطابقة لا تزال تامة، لكن:
~ بدلًا من =.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
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.
في هذا التمرين سنحاكي الجولة الأولى من لعبة Blackjack.
ستتلقى بطاقتين وستتمكن من رؤية البطاقة المكشوفة للموزّع. تُمثَّل جميع البطاقات باستخدام سلسلة نصية مثل "ace" و"king" و"three" و"two" وغيرها. وقيم كل بطاقة كالتالي:
| بطاقة | قيمة | بطاقة | قيمة |
|---|---|---|---|
| ace | 11 | eight | 8 |
| two | 2 | nine | 9 |
| three | 3 | ten | 10 |
| four | 4 | jack | 10 |
| five | 5 | queen | 10 |
| six | 6 | king | 10 |
| seven | 7 | other | 0 |
ملاحظة: عادةً يمكن لبطاقات "ace" أن تأخذ القيمة 1 أو 11، لكن للتبسيط سنفترض أنها تأخذ القيمة 11 فقط.
بناءً على بطاقتيك وبطاقة الموزّع، توجد استراتيجية للجولة الأولى من اللعبة، تكون فيها الخيارات التالية:
ورغم أنها ليست مثالية بعد، ستتبع الاستراتيجية التي كان صديقك Alex يطوّرها، وهي كالتالي:
نفّذ دالة parse_card لحساب القيمة الرقمية لبطاقة:
parse_card("ace")
# => 11
اكتب دالة first_turn تنفّذ منطق القرار كما وُصف أعلاه:
first_turn(card1, card2, dealer_card)
إليك بعض الأمثلة على النتائج المتوقعة:
first_turn("ace", "ace", "jack") == "P"
first_turn("ace", "king", "ace") == "S"
first_turn("five", "queen", "ace") == "H"
سجّل في Exercism لتتعلّم وتتقن R عبر 21 مفهومًا111 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.