Các lamdas lồng nhau: MapThreading a MapAt lambda

Oct 10 2020

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

7 kglr Oct 10 2020 at 01:06
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}}}
4 m_goldberg Oct 10 2020 at 05:56

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}}}
3 WReach Oct 10 2020 at 21:11

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