reduce() وaccumulate() وwalk()
اطوِ القوائم وابنِ نتائج تراكمية وطبّق التأثيرات الجانبية باستخدام walk().
reduce() وaccumulate() وwalk() درس مجاني في R Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في R Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة R Academy 4 دروس في المجموع.
ما بعد map() — دوال purrr الأخرى
في حين تطبّق map() دالة بصورة مستقلة على كل عنصر، تتطلب بعض المهام عمليات تدمج العناصر (reduce)، أو تراكم النتائج الوسيطة، أو تطبّق الدوال لأغراض الآثار الجانبية فقط (walk). يوفر purrr دوال مخصصة لكل حالة.
library(purrr)
# Example: combining a list of numbers into a single value
nums <- list(1, 2, 3, 4, 5)
# We want: 1 + 2 + 3 + 4 + 5 = 15
# map() can't do this — it returns 5 separate results
# reduce() folds the list into one value
result <- reduce(nums, `+`)
cat('Sum via reduce:', result)reduce() — اختزال قائمة إلى قيمة واحدة
تطبّق reduce(.x, .f, .init) الدالة .f تراكميًا على عناصر .x من اليسار إلى اليمين، فتختزل القائمة إلى قيمة واحدة. يحسب reduce(list(a,b,c), f) التعبير f(f(a,b),c).
library(purrr)
# reduce with max: find the overall maximum
values <- list(42, 17, 89, 55, 23)
result <- reduce(values, max)
cat('Maximum:', result, '\n')
# reduce with paste: concatenate strings
words <- list('The', 'quick', 'brown', 'fox')
reduce(words, paste)استخدام reduce() مع .init
يوفر الوسيط .init قيمة بدء (بذرة). ويصبح الاستدعاء الأول f(.init, x[1]). وهذا ضروري عندما تكون القائمة فارغة محتملًا، إذ تُختزل إلى .init، أو عندما تحتاجون إلى حالة بدء محددة.
library(purrr)
# Running count of elements matching a condition
data <- list(5, 12, 3, 18, 7, 15, 2)
# Count values greater than 10, starting from 0
reduce(data, function(count, x) count + (x > 10), .init = 0L)
# Also useful for string building:
reduce(c('A','B','C'), paste, sep='-', .init='START')reduce() مع إطارات البيانات — تسلسل عمليات الدمج
من أقوى استخدامات reduce() دمج قائمة من إطارات البيانات. فبدلًا من كتابة left_join(left_join(df1, df2), df3)، استخدموا reduce(list_of_dfs, left_join, by='key').
library(purrr)
library(dplyr)
base_df <- data.frame(id=1:3, name=c('Alice','Bob','Carol'))
scores <- data.frame(id=1:3, score=c(85,90,78))
grades <- data.frame(id=1:3, grade=c('B','A','C'))
city <- data.frame(id=1:3, city=c('NYC','LA','Chicago'))
dfs <- list(base_df, scores, grades, city)
reduce(dfs, left_join, by='id')accumulate() — الاحتفاظ بالنتائج الوسيطة
تشبه accumulate(.x, .f) الدالة reduce()، لكنها تحتفظ بجميع القيم الوسيطة. وتُرجع متجهًا (أو قائمة) بالطول نفسه لطول المدخل، يعرض النتيجة المتراكمة بعد كل خطوة.
library(purrr)
# Running sum — same as cumsum() but via accumulate
values <- c(100, 120, 95, 140, 160)
accumulate(values, `+`)
# Running maximum
accumulate(c(50, 52, 48, 55, 53, 58), max)استخدام accumulate() للنتائج خطوة بخطوة
تكون accumulate() مفيدة خصوصًا لتتبّع خطوات الخوارزميات، أو إنشاء السلاسل النصية حرفًا بعد حرف، أو أي عملية تريدون فيها فحص كل حالة وسيطة، لا النتيجة النهائية فقط.
library(purrr)
# Compound interest step by step
principal <- 1000
rates <- c(0.05, 0.05, 0.05, 0.05, 0.05) # 5% per year
accumulate(rates, function(balance, rate) {
round(balance * (1 + rate), 2)
}, .init = principal)walk() — آثار جانبية دون قيمة مُرجعة
تطبّق walk(.x, .f) الدالة .f على كل عنصر من .x لأغراض آثارها الجانبية فقط، مثل الطباعة أو كتابة الملفات أو إرسال الرسائل. وتُرجع .x بصورة غير مرئية، لذا يمكنكم استخدامها في مسار دون قطع سلسلته.
library(purrr)
# Print a summary for each dataset
datasets <- list(
mtcars = mtcars[,1:3],
iris = iris[,1:3]
)
walk(datasets, function(df) {
cat('Rows:', nrow(df), '| Cols:', ncol(df),
'| NAs:', sum(is.na(df)), '\n')
})استخدام walk() في مسار
بما أن walk() تُرجع .x بصورة غير مرئية، يمكنكم إدراجها في مسار dplyr لتسجيل النتائج الوسيطة أو طباعتها دون قطع التدفق. فكّروا فيها كنقطة تمرير للتنقيح أو التسجيل.
library(purrr)
library(dplyr)
results <- list(
East = data.frame(rep=c('A','B'), sales=c(100,120)),
West = data.frame(rep=c('C','D'), sales=c(200,190))
)
# Log each region's data, then continue processing
region_totals <- results %>%
walk(~cat('Processing:', nrow(.x), 'rows\n')) %>%
map_dbl(~sum(.x$sales))
print(region_totals)walk2() — آثار جانبية مع مدخلين
تمثل walk2(.x, .y, .f) النسخة ذات المدخلين من walk(). ومن حالات استخدامها الشائعة كتابة إطارات بيانات متعددة في ملفات، حيث تكون .x قائمة إطارات البيانات و.y قائمة مسارات الملفات.
library(purrr)
data_list <- list(
east = data.frame(x=1:3, y=4:6),
west = data.frame(x=7:9, y=10:12)
)
file_paths <- list(
'/tmp/east_data.csv',
'/tmp/west_data.csv'
)
# Write each data frame to its corresponding path
walk2(data_list, file_paths, function(df, path) {
write.csv(df, path, row.names=FALSE)
cat('Written:', path, '\n')
})iwalk() — walk مع فهرس
تشبه iwalk(.x, .f) الدالة walk()، لكنها تمرّر اسم العنصر (أو فهرسه) بوصفه الوسيط الثاني .y. ويفيد ذلك عندما تحتاجون إلى معرفة العنصر الذي تجري معالجته ضمن الأثر الجانبي.
library(purrr)
region_counts <- list(East=150, West=200, North=85, South=120)
# Print each region with its rank
iwalk(region_counts, function(count, name) {
cat(name, ':', count, 'customers\n')
})reduce_right() — اختزال من اليمين إلى اليسار
تطبّق reduce(.x, .f, .dir='backward') (أو reduce_right() المهملة) الدالة من اليمين إلى اليسار: f(a, f(b, f(c, d))). ويهم ذلك في العمليات غير التبادلية، مثل الطرح أو إنشاء السلاسل النصية.
library(purrr)
words <- c('fox','brown','quick','The')
# Left-to-right: 'The quick brown fox'
reduce(rev(words), paste)
# Right-to-left: same effect but starting from right
reduce(words, function(a, b) paste(b, a))تحقق سريع
متى تستخدمون walk() بدلًا من map()؟
مراجعة: reduce وaccumulate وwalk
أهم النقاط حول reduce وaccumulate وwalk:
reduce(.x, .f)— تختزل قائمة إلى قيمة واحدة من اليسار إلى اليمين؛ ويحدد.initقيمة البدءreduce(list_of_dfs, left_join)— نمط قوي لتسلسل عمليات الدمجaccumulate(.x, .f)— تشبه reduce، لكنها تُرجع جميع النتائج الوسيطةwalk(.x, .f)— تُطبّق لأغراض الآثار الجانبية، مثل الطباعة والكتابة والتسجيل؛ وتُرجع.xwalk2(.x, .y, .f)— walk بمدخلين، مثل إطار بيانات ومسار ملفiwalk(.x, .f)— walk مع اسم العنصر بوصفه الوسيط الثاني
library(purrr)
library(dplyr)
# reduce() joins a list of data frames, accumulate() shows interim states
monthly_sums <- c(100, 120, 95, 140, 160, 130)
cat('reduce (total): ', reduce(monthly_sums, `+`), '\n')
cat('accumulate (running):', accumulate(monthly_sums, `+`), '\n')
# walk() for side-effect logging
results <- list(a=42, b=17, c=89)
walk(results, ~cat('Value:', .x, '\n'))الأسئلة الشائعة
هل درس «reduce() وaccumulate() وwalk()» مجاني؟
نعم — نص درس «reduce() وaccumulate() وwalk()» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة R Academy، انتقل إلى CoddyKit PRO. تتضمن دورة R Academy 4 دروس في المجموع.
ماذا ستتعلم في «reduce() وaccumulate() وwalk()»؟
اطوِ القوائم وابنِ نتائج تراكمية وطبّق التأثيرات الجانبية باستخدام walk(). تتمرن على R Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ R Academy؟
لا تُشترط خبرة سابقة. R Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «reduce() وaccumulate() وwalk()»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس R Academy هذا؟
نعم. كل درس في R Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- map() ومتغيراته ذات الأنواع
- map2() وpmap() لمدخلات متعددة
- reduce() وaccumulate() وwalk()
- keep() وdiscard() وتصفية القوائم