Các lamdas lồng nhau: MapThreading a MapAt lambda
Hãy xem xét một bộ (ở đây) 3 loạt
r`data = Thread[{Range@4, # Range@4}] & /@ (10 Range@3);
(*{
{{1, 10}, {2, 20}, {3, 30}, {4, 40}},
{{1, 20}, {2, 40}, {3, 60}, {4, 80}},
{{1, 30}, {2, 60}, {3, 90}, {4, 120}}
}*)
Mục đích là chia tọa độ thứ hai của mỗi điểm trong mỗi chuỗi cho một số ước divs[[i]]
r`divs = 10 Range@3;
(*{10, 20, 30}*)
Tôi hiện đang đạt được điều này như sau
r`f[x_] := #/x &
MapThread[MapAt[r`f@#2, #1, {All, 2}] &, {r`data, r`divs}]
(*{
{{1, 1}, {2, 2}, {3, 3}, {4, 4}},
{{1, 1}, {2, 2}, {3, 3}, {4, 4}},
{{1, 1}, {2, 2}, {3, 3}, {4, 4}}
}*)
Làm thế nào để loại bỏ có r`flợi cho việc lồng trực tiếp lambda bộ phận #/x &, hiện diện trong MapAt, bên trong MapThread?
Nói cách khác, làm thế nào để viết một cách chính xác một cái gì đó thuộc loại
MapThread[MapAt[#/#2 &, #1, {All, 2}] &, {r`data, r`divs}]
^
|
|
should refer to second coord of point
and not r`data[[i]]
Xin lưu ý rằng tôi đã trải qua các câu hỏi tương tự (ví dụ: MapThread trên Bản đồ lồng nhau ) nhưng không thể áp dụng giải pháp của chúng cho trường hợp hiện tại.
Trả lời
MapThread[MapAt[z \[Function] z/#2, #1, {All, 2}] &, {r`data, r`divs}]
hoặc là
MapThread[MapAt[Function[z, z/#2], #1, {All, 2}] &, {r`data, r`divs}]
hoặc là
MapThread[Function[{x, y}, MapAt[#/y &, x, {All, 2}]], {r`data, r`divs}]
{{{1, 1}, {2, 2}, {3, 3}, {4, 4}}, {{1, 1}, {2, 2}, {3, 3}, {4, 4}}, {{1, 1}, {2, 2}, {3, 3}, {4, 4}}}
Ngoài ra,
Transpose[Transpose[#]/{1, #2}] & @@@ Transpose[{r`data, r`divs}]
MapThread[Transpose[Transpose[#]/{1, #2}] &, {r`data, r`divs}]
MapThread[ReplacePart[#, {i_, 2} :> #[[i, 2]]/#2] &, {r`data, r`divs}]
SubsetMap[Flatten[Partition[#, First[Length /@ r`data]]/r`divs] &, r`data,
{All, All, 2}]
Module[{z = r`data}, z[[All, All, 2]] = z[[All, All, 2]]/r`divs;z]
tất cả cho
{{{1, 1}, {2, 2}, {3, 3}, {4, 4}}, {{1, 1}, {2, 2}, {3, 3}, {4, 4}}, {{1, 1}, {2, 2}, {3, 3}, {4, 4}}}
Và ... một Halloween đặc biệt:
☺[{r`data, r`divs}]
{{{1, 1}, {2, 2}, {3, 3}, {4, 4}}, {{1, 1}, {2, 2}, {3, 3}, {4, 4}}, {{1, 1}, {2, 2}, {3, 3}, {4, 4}}}
Bằng cách sử dụng ReplacePartthay cho bất kỳ hàm ánh xạ nào, không cần phải xác định bất kỳ hàm nào, không rõ ràng như hàm của bạn r`fcũng như không phải là một hàm thuần túy.
data = Thread[{Range @ 4, # Range @ 4}]& /@ (10 Range @ 3);
divisors = 10 Range @ 3;
ReplacePart[
data,
{i_, j_} :> Module[{m = data[[i, j]]}, m[[2]] = m[[2]]/divisors[[i]]; m]]
{{{1, 1}, {2, 2}, {3, 3}, {4, 4}}, {{1, 1}, {2, 2}, {3, 3}, {4, 4}}, {{1, 1}, {2, 2}, {3, 3}, {4, 4}}}
Trong phiên bản Mathematica 12.1+, chúng ta có thể sử dụng OperatorApplied để đưa đối số bên ngoài vào hàm bên trong:
MapThread[MapAt[OperatorApplied[#/#2&][#2], #1, {All, 2}] &, {r`data, r`divs}]
(*
{{1, 1}, {2, 2}, {3, 3}, {4, 4}},
{{1, 1}, {2, 2}, {3, 3}, {4, 4}},
{{1, 1}, {2, 2}, {3, 3}, {4, 4}}
*)
Curry từ phiên bản 11.3+ cũng làm được điều tương tự nhưng giờ đây đã bị coi là lỗi thời. Để biết thêm chi tiết về những công trình này và các công trình liên quan, hãy xem (197168) .