lamdas ที่ซ้อนกัน: MapThreading a MapAt lambda

Oct 10 2020

พิจารณาชุด (ที่นี่) 3 ชุด


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}}
}*)

เจตนาคือการหารพิกัดที่สองของแต่ละจุดในแต่ละอนุกรมด้วยตัวหารบางตัว divs[[i]]

r`divs = 10 Range@3;
(*{10, 20, 30}*)

ฉันกำลังบรรลุสิ่งนี้ดังต่อไปนี้

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}}
}*)

วิธีกำจัดr`fในการทำรังของส่วนแลมด้าโดยตรง#/x &ซึ่งมีอยู่ในMapAtด้านในMapThread?

กล่าวอีกนัยหนึ่งวิธีการเขียนสิ่งที่ถูกต้อง

MapThread[MapAt[#/#2 &, #1, {All, 2}] &, {r`data, r`divs}]
                ^           
                |
                |
      should refer to second coord of point
             and not r`data[[i]]

โปรดทราบว่าฉันเคยผ่านคำถามที่คล้ายกัน (เช่นMapThread บนแผนที่ที่ซ้อนกัน ) แต่ไม่สามารถใช้วิธีแก้ปัญหากับกรณีปัจจุบันได้

คำตอบ

7 kglr Oct 10 2020 at 01:06
MapThread[MapAt[z \[Function] z/#2, #1, {All, 2}] &, {r`data, r`divs}]

หรือ

MapThread[MapAt[Function[z, z/#2], #1, {All, 2}] &, {r`data, r`divs}]

หรือ

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}}}

หรืออีกทางหนึ่ง

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]

ทั้งหมดให้

{{{1, 1}, {2, 2}, {3, 3}, {4, 4}}, {{1, 1}, {2, 2}, {3, 3}, {4, 4}},
 {{1, 1}, {2, 2}, {3, 3}, {4, 4}}} 

และ ... พิเศษสำหรับวันฮาโลวีน:

☺[{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

ด้วยการใช้ReplacePartแทนฟังก์ชันการทำแผนที่ใด ๆ คุณจึงไม่จำเป็นต้องกำหนดฟังก์ชันใด ๆ ทั้งไม่เหมือนกับฟังก์ชันของคุณอย่างชัดเจนr`fหรือเป็นฟังก์ชันที่บริสุทธิ์

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

ในMathematicaเวอร์ชัน 12.1+ เราสามารถใช้OperatorAppliedเพื่อฉีดอาร์กิวเมนต์ด้านนอกลงในฟังก์ชันด้านใน:

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จากเวอร์ชัน 11.3+ ทำสิ่งเดียวกัน แต่ตอนนี้ถือว่าล้าสมัยแล้ว สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการก่อสร้างเหล่านี้และที่เกี่ยวข้องดู(197,168)