Map và mapply
Thuộc phần Logic và luồng điều khiển trong hành trình R của Coddy. Bài học 33 trên 64.
Map(f, xs, ys) duyệt đồng thời qua hai hoặc nhiều vector và gọi f với một phần tử từ mỗi vector: trước tiên với các phần tử đầu tiên, sau đó với các phần tử thứ hai, cứ thế tiếp tục. Hàm này trả về một danh sách:
totals <- Map(function(q, p) q * p, c(2, 1, 3), c(4, 12, 2.5))
print(length(totals))
print(totals[[3]])Đầu ra:
[1] 3
[1] 7.5mapply() là phiên bản đơn giản hóa, tương tự sapply() khi dùng với nhiều vector. unlist() cũng làm phẳng danh sách từ Map() thành một vector:
print(mapply(function(q, p) q * p, c(2, 1, 3), c(4, 12, 2.5)))
print(unlist(Map(function(a, b) a + b, 1:3, 4:6)))Đầu ra:
[1] 8.0 12.0 7.5
[1] 5 7 9Các vectơ được ghép theo vị trí, vì vậy chúng phải có cùng độ dài. mapply() đặt tên cho các kết quả dạng văn bản theo vectơ đầu tiên; USE.NAMES = FALSE xóa các tên:
items <- c("tea", "jam")
qty <- c(2, 3)
labels <- mapply(function(i, q) paste(q, "x", i), items, qty, USE.NAMES = FALSE)
print(labels)Đầu ra:
[1] "2 x tea" "3 x jam"Khi mỗi cặp cần có một câu lệnh if, hãy viết một hàm có nhiều đối số rồi truyền hàm đó cho mapply(). Khi đó, điều kiện sẽ chạy một lần cho mỗi cặp:
describe <- function(name, age) {
group <- if (age < 18) "minor" else "adult"
paste0(name, " (", group, ")")
}
print(mapply(describe, c("Ada", "Tim"), c(36, 12), USE.NAMES = FALSE))Đầu ra:
[1] "Ada (adult)" "Tim (minor)"Thử thách
DễHoàn thiện order_lines(items, qty, prices). Trả về một dòng cho mỗi mặt hàng, 2 x tea = 8.00: số lượng, x , mặt hàng, = và số lượng nhân với giá, làm tròn đến hai chữ số thập phân. Dùng mapply() hoặc Map().
Code được cung cấp đọc mặt hàng, số lượng và giá từ ba dòng, mỗi dòng gồm các giá trị phân tách bằng dấu phẩy, rồi in ra từng dòng được trả về.
Tự làm thử
order_lines <- function(items, qty, prices) {
# Viết code của bạn ở đây
character(0)
}
# Đoạn code đầu vào/đầu ra được cung cấp sẵn: giữ nguyên
input <- suppressWarnings(readLines(file("stdin")))
cat(order_lines(strsplit(input[1], ",")[[1]], as.numeric(strsplit(input[2], ",")[[1]]), as.numeric(strsplit(input[3], ",")[[1]])), sep = "\n")
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Logic và luồng điều khiển
1Chuỗi chuyên sâu
Chuỗi con với substr()Định dạng với sprintf()Tách và nối chuỗiTìm kiếm trong chuỗiThay thế văn bảnÔn tập: Tạo tên người dùng10Luồng điều khiển nâng cao
Hàm switch()ifelse() dạng vector hóarepeat và breakHàm đệ quyÔn tập: phân loại điểmTự luyện tập: Trình biên dịch R online