Menu
CoddyTech

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.5

mapply() 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 9

Cá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)"
challenge icon

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")
quiz iconTự kiểm tra

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

Tự luyện tập: Trình biên dịch R online