0Pricing
R Academy · درس

keep() وdiscard() وتصفية القوائم

صفِّ عناصر القوائم باستخدام دوال التنبؤ لبناء مسارات عمل واضحة.

keep() وdiscard() وتصفية القوائم درس مجاني في R Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في R Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة R Academy 4 دروس في المجموع.

تصفية القوائم باستخدام purrr

يوفر purrr مجموعة من الدوال لـتصفية القوائم والبحث فيها واختبارها استنادًا إلى الدوال الاختبارية. والدالة الاختبارية هي دالة تُرجع TRUE أو FALSE. وتحل هذه الدوال محل استدعاءات Filter() المطوّلة والحلقات الشرطية.

library(purrr)

# A mixed list to filter
mixed <- list(1L, 'hello', 3.14, NULL, TRUE, 42L, 'world', NULL)

cat('Total elements:', length(mixed), '\n')
cat('Non-NULL elements:', length(compact(mixed)))

keep() — الاحتفاظ بالعناصر المطابقة لدالة اختبارية

تحتفظ keep(.x, .p) بالعناصر التي تُرجع الدالة الاختبارية .p لها القيمة TRUE فقط. وهي عكس discard(). ويمكن أن تكون الدالة الاختبارية اسم دالة أو صيغة أو متجهًا منطقيًا.

library(purrr)

mixed <- list(1L, 'hello', 3.14, TRUE, 42L, 'world', 2.7)

# Keep only numeric values
numeric_only <- keep(mixed, is.numeric)
print(numeric_only)

# Keep values greater than 5
keep(mixed, ~is.numeric(.x) && .x > 5)

discard() — إزالة العناصر المطابقة لدالة اختبارية

تزيل discard(.x, .p) العناصر التي تُرجع الدالة الاختبارية لها القيمة TRUE، وتحتفظ بالباقي. وهي النظير المقابل لـ keep(). استخدموها لتصفية القيم الخالية أو قيم NA أو الأنواع غير المرغوبة من القائمة.

library(purrr)

results <- list(
  model_a = list(rmse=2.5, converged=TRUE),
  model_b = list(rmse=NA, converged=FALSE),
  model_c = list(rmse=1.8, converged=TRUE),
  model_d = list(rmse=NA, converged=FALSE)
)

# Discard models that did not converge
converged_models <- discard(results, ~!.x$converged)
map_dbl(converged_models, ~.x$rmse)

compact() — إزالة عناصر NULL

تزيل compact(.x) جميع عناصر NULL من القائمة، وهي مكافئة لـ discard(.x, is.null) لكنها أكثر إيجازًا. وتفيد خصوصًا بعد استدعاءات map() التي قد تُرجع NULL لبعض المدخلات.

library(purrr)

# Simulate fetching data that might return NULL
ids <- 1:6
fetch_data <- function(id) {
  if (id %% 2 == 0) NULL else list(id=id, value=id*10)
}

raw_results <- map(ids, fetch_data)
cat('With NULLs:', length(raw_results), '\n')

clean_results <- compact(raw_results)
cat('Without NULLs:', length(clean_results))

detect() — العثور على أول تطابق

تُرجع detect(.x, .p) أول عنصر يحقق الدالة الاختبارية. وإذا لم يطابق أي عنصر، فإنها تُرجع NULL. استخدموا detect(.right=TRUE) للبحث من اليمين والعثور على آخر تطابق.

library(purrr)

prices <- list(15.99, 8.50, 23.99, 5.25, 19.99, 4.75)

# Find first price under $10
first_cheap <- detect(prices, ~.x < 10)
cat('First price under $10:', first_cheap, '\n')

# Find last price under $10
last_cheap <- detect(prices, ~.x < 10, .right=TRUE)
cat('Last price under $10:', last_cheap)

detect_index() — العثور على موضع أول تطابق

تُرجع detect_index(.x, .p) فهرس أول عنصر يحقق الدالة الاختبارية، أو 0L إذا لم يُعثر على أي عنصر. وتفيد عندما تحتاجون إلى الموضع لا إلى القيمة، مثل تحديث ذلك العنصر أو استخراجه.

library(purrr)

models <- list(
  list(name='lm', rmse=3.5),
  list(name='rf', rmse=2.1),
  list(name='xgb', rmse=1.8),
  list(name='svm', rmse=2.4)
)

# Find the index of the best model (lowest RMSE)
best_idx <- detect_index(models, function(m) m$rmse < 2.0)
cat('Best model index:', best_idx, '\n')
cat('Best model name:', models[[best_idx]]$name)

every() — هل تطابق جميع العناصر؟

تُرجع every(.x, .p) القيمة TRUE إذا تحققت الدالة الاختبارية لكل عنصر. وتتوقف عند أول FALSE. وهي مكافئة لـ all(map_lgl(.x, .p))، لكنها تُقيَّم عند الحاجة.

library(purrr)

batch_results <- list(
  list(status='success', rows=150),
  list(status='success', rows=200),
  list(status='success', rows=175)
)

failed_batch <- list(
  list(status='success', rows=150),
  list(status='error', rows=0),
  list(status='success', rows=175)
)

cat('All success (good):', every(batch_results, ~.x$status == 'success'), '\n')
cat('All success (bad):', every(failed_batch, ~.x$status == 'success'))

some() — هل يطابق أي عنصر؟

تُرجع some(.x, .p) القيمة TRUE إذا حقق عنصر واحد على الأقل الدالة الاختبارية. وتتوقف عند أول TRUE. وهي مكافئة لـ any(map_lgl(.x, .p))، لكنها تُقيَّم عند الحاجة.

library(purrr)

datasets <- list(
  data.frame(x=1:3, y=c(1,NA,3)),
  data.frame(x=4:6, y=7:9),
  data.frame(x=7:9, y=c(NA,NA,NA))
)

# Does any dataset contain NAs?
cat('Any NAs:', some(datasets, anyNA), '\n')

# Is every dataset NA-free?
cat('All clean:', every(datasets, ~!anyNA(.x)))

none() — هل لا يطابق أي عنصر؟

تُرجع none(.x, .p) القيمة TRUE إذا لم يحقق أي عنصر الدالة الاختبارية. وهي مكافئة لـ !some(.x, .p)، لكنها أوضح في سياقات التحقق التي تريدون فيها التأكد من غياب شرط ما.

library(purrr)

api_responses <- list(
  list(code=200, data='OK'),
  list(code=200, data='OK'),
  list(code=201, data='Created')
)

# Ensure no errors occurred
no_errors <- none(api_responses, ~.x$code >= 400)
cat('No errors:', no_errors, '\n')

# Check another batch
bad_batch <- c(api_responses, list(list(code=500, data='Error')))
none(bad_batch, ~.x$code >= 400)

دمج keep() مع map()

يُعدّ تسلسل keep() (أو discard()) مع map() نمطًا شائعًا: إذ تُرشَّح القائمة أولًا للاحتفاظ بالعناصر ذات الصلة، ثم يُطبَّق عليها تحويل. وبهذا ينفصل منطق التصفية عن منطق المعالجة بوضوح.

library(purrr)

model_results <- list(
  list(name='A', converged=TRUE, rmse=2.5),
  list(name='B', converged=FALSE, rmse=NA),
  list(name='C', converged=TRUE, rmse=1.8),
  list(name='D', converged=TRUE, rmse=3.1)
)

# Keep converged, extract RMSE
model_results %>%
  keep(~.x$converged) %>%
  map_dbl(~.x$rmse)

استخدام keep() مع دوال is.*

تعمل دوال التحقّق المضمّنة في R من نمط is.* (is.numeric وis.character وis.null وis.na وis.finite) مباشرةً بصفتها دوال تحقّق داخل keep() وdiscard()، من دون الحاجة إلى تغليفها بالرمز ~.

library(purrr)

mixed_env <- list(
  count = 42L,
  name = 'Alice',
  ratio = 3.14,
  flag = TRUE,
  missing = NULL,
  data = data.frame(x=1:3)
)

# Extract different types
numeric_items <- keep(mixed_env, is.numeric)
cat('Numeric items:', length(numeric_items), '\n')

# Remove NULL items
cleaned <- discard(mixed_env, is.null)
cat('After removing NULL:', length(cleaned))

تحقّق سريع

ماذا تُرجع detect(.x, .p) عندما لا يحقّق أي عنصر في .x دالة التحقّق .p؟

مراجعة: دوال تصفية القوائم

أهم النقاط حول أدوات purrr لتصفية القوائم:

  • keep(.x, .p) — الاحتفاظ بالعناصر التي تكون فيها دالة التحقّق TRUE
  • discard(.x, .p) — إزالة العناصر التي تكون فيها دالة التحقّق TRUE
  • compact(.x) — إزالة جميع العناصر NULL
  • detect(.x, .p) — إرجاع أول عنصر يطابق دالة التحقّق (أو NULL)
  • detect_index(.x, .p) — إرجاع فهرس أول تطابق (أو 0L)
  • every(.x, .p) — إرجاع TRUE إذا طابقت جميع العناصر الشرط
  • some(.x, .p) — إرجاع TRUE إذا طابق أي عنصر الشرط
  • none(.x, .p) — إرجاع TRUE إذا لم يطابق أي عنصر الشرط
library(purrr)

scores <- list(45, 72, 88, 53, 91, 67, 39, 85)

passing <- keep(scores, ~.x >= 60)
failing <- discard(scores, ~.x >= 60)

cat('Passing:', length(passing), 'students\n')
cat('Failing:', length(failing), 'students\n')
cat('All pass:', every(scores, ~.x >= 60), '\n')
cat('Any fail:', some(scores, ~.x < 60), '\n')
cat('First pass score:', detect(scores, ~.x >= 60))

الأسئلة الشائعة

هل درس «keep() وdiscard() وتصفية القوائم» مجاني؟

نعم — نص درس «keep() وdiscard() وتصفية القوائم» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة R Academy، انتقل إلى CoddyKit PRO. تتضمن دورة R Academy 4 دروس في المجموع.

ماذا ستتعلم في «keep() وdiscard() وتصفية القوائم»؟

صفِّ عناصر القوائم باستخدام دوال التنبؤ لبناء مسارات عمل واضحة. تتمرن على R Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ R Academy؟

لا تُشترط خبرة سابقة. R Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «keep() وdiscard() وتصفية القوائم»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس R Academy هذا؟

نعم. كل درس في R Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. map() ومتغيراته ذات الأنواع
  2. map2() وpmap() لمدخلات متعددة
  3. reduce() وaccumulate() وwalk()
  4. keep() وdiscard() وتصفية القوائم
← العودة إلى R Academy