2012-01-06 30 views
7

Simple câu hỏi, đưa ra một danh sách như thế nàyLàm thế nào để loại bỏ các phụ {} khi Lập bản đồ một chức năng vào một danh sách

Clear[a, b, c, d, e, f]; 
lst = {{a, b}, {c, d}, {e, f}}; 

và cho rằng tôi có một hàm được định nghĩa như thế này:

foo[x_,y_]:=Module[{},...] 

Và Tôi muốn áp dụng chức năng này vào danh sách, vì vậy Nếu tôi nhập

Map[foo, lst] 

Điều này cung cấp

{foo[{a, b}], foo[{c, d}], foo[{e, f}]} 

Tôi muốn nó đi ra như

{foo[a, b], foo[c, d], foo[e, f]} 

để nó hoạt động.

Cách tốt nhất để làm điều này là gì? Giả sử tôi không thể thay đổi chức năng foo [] định nghĩa (nói nó là xây dựng-in)

Chỉ 2 cách tôi biết bây giờ là

Map[foo[#[[1]], #[[2]]] &, lst] 
{foo[a, b], foo[c, d], foo[e, f]} 

(quá nhiều công việc), hoặc

MapThread[foo, Transpose[lst]] 
{foo[a, b], foo[c, d], foo[e, f]} 

(ít đánh máy hơn, nhưng cần phải chuyển vị trí trước)

Câu hỏi: Còn cách nào khác tốt hơn để làm điều này? Tôi đã xem bản đồ khác và bạn bè của nó, và tôi không thể nhìn thấy một chức năng để làm điều đó trực tiếp hơn những gì tôi có.

+1

[Liên quan] (http://stackoverflow.com/q/5746717/499167) câu hỏi: ** Áp dụng danh sách cho các đối số trong Mathematica ** – tomd

Trả lời

14

Bạn cần Apply tại Level 1 hoặc hình thức ngắn của nó, @@@

[email protected]@@lst  
{foo[a, b], foo[c, d], foo[e, f]} 
7

Một cách có thể là thay đổi người đứng đầu mỗi phần tử của lst từ List để foo:

foo @@ # & /@ lst 
{foo[a, b], foo[c, d], foo[e, f]} 
4

Một vài chi tiết khả năng để chọn từ:

Cái này tôi s một phiên bản chi tiết hơn về câu trả lời của yoda.Nó áp dụng foo ở mức 1 của danh sách lst chỉ (thay thế người đứng đầu List với người đứng đầu foo):

Apply[foo, lst, {1}] 

này không giống nhau, nhưng bản đồ Apply qua danh sách lst (thực chất là Andrei của câu trả lời):

Map[Apply[foo, #] &, lst ] 

Và điều này chỉ thay thế Danh sách mẫu [x__] với foo [x] ở mức 1:

Replace[lst, List[x__] -> foo[x], 1] 
6

Chỉ cần báo cáo thử nghiệm hiệu năng khó hiểu của phương pháp cả hai (@@@, @@ # & /@):

 T = RandomReal[{1,100}, {1000000, 2}]; 

     H[F_Symbol, T_List] := 

        [email protected][F @@@ T;]/[email protected][F @@ # & /@ T;] 

     Table[{ToString[F], H[F, T]}, {F, {Plus, Subtract, Times, Divide, Power, Log}}] 

Out[3]= {{"Plus",  4.174757}, 
     {"Subtract", 0.2596154}, 
     {"Times", 3.928230}, 
     {"Divide", 0.2674164}, 
     {"Power", 0.3148629}, 
     {"Log",  0.2986936}} 

Các kết quả này không phải ngẫu nhiên, nhưng khoảng tỷ lệ thuận với kích thước dữ liệu rất khác nhau.

@@@ là khoảng 3-4 lần nhanh hơn cho Subtract, Divide, Power, Log khi @@ # & /@ là nhanh hơn gấp 4 lần cho PlusTimes làm phát sinh một câu hỏi, trong đó (như người ta có thể tin rằng) có thể là một chút
làm rõ bởi việc đánh giá sau:

[email protected]{Plus, Subtract, Times, Divide, Power, Log} 

chỉ PlusTimes có các thuộc tính FlatOrderless, trong khi số còn lại chỉ Power (có vẻ tương đối hiệu quả nhất ở đó) cũng có thuộc tính OneIdentity.

Sửa

Một lời giải thích đáng tin cậy để nâng cao hiệu suất quan sát được (nhờ nhận xét Leonid Shifrin của) nên đi dọc theo một con đường khác.

Theo mặc định, có MapCompileLength -> 100 vì chúng tôi có thể kiểm tra đánh giá SystemOptions["CompileOptions"]. Để thiết lập lại autocompilation của Bản đồ chúng ta có thể đánh giá:

SetSystemOptions["CompileOptions" -> "MapCompileLength" -> Infinity] 

Bây giờ chúng ta có thể kiểm tra hiệu suất tương đối của các phương pháp cả hai bằng cách đánh giá một lần nữa H của chúng tôi - chức năng kiểm tra hiệu suất trên biểu tượng có liên quan và danh sách:

  Table[{ToString[F], H[F, T]}, {F, {Plus, Subtract, Times, Divide, Power, Log}}] 

Out[15]= {{"Plus",  0.2898246}, 
      {"Subtract", 0.2979452}, 
      {"Times",  0.2721893}, 
      {"Divide", 0.3078512}, 
      {"Power",  0.3321622}, 
      {"Log",  0.3258972}} 

Có những kết quả này chúng ta có thể kết luận rằng cách tiếp cận chung của Yoda (@@@) là hiệu quả nhất, trong khi đó Andrei cung cấp tốt hơn trong trường hợp PlusTimes do biên dịch tự động Map cho phép p tốt hơn sự biến dạng của (@@ # & /@).

+3

Không quá khó hiểu nếu chúng ta nhớ rằng bản đồ 'tự động biên dịch khi có thể, và 'Áp dụng' có thể được biên dịch chỉ với 3 đầu:' Plus', 'Times' và' List'. OTOH, '@@@' không tự động biên dịch. Bạn thấy hiệu quả tăng cho 'Plus' và' Times' do tự động biên dịch trong cấu trúc '@@ # &/@', và bởi vì đầu vào của bạn là một mảng được đóng gói lớn (cho phép một lợi ích từ tự động biên dịch) –

+1

Xem thêm câu trả lời này của tôi: http://stackoverflow.com/questions/6405304/memory-use-of-apply-vs-map-virtual-memory-use-and-lock-ups/6408489#6408489 và các nhận xét bên dưới, cho thảo luận thêm về các vấn đề tương tự. –

+0

@Leonid Cảm ơn bạn đã liên kết và nhận xét thú vị. Thật vậy, khi tôi đánh giá hàm 'H' của tôi trên' T1 = FromPackedArray [T] 'hiệu quả tương đối của' Plus' và 'Times' chậm lại theo hệ số 2, trong khi các hàm khác chỉ bằng một vài phần trăm, tuy nhiên' 'vẫn nhanh hơn gấp hai lần' Plus' và 'Times'. Lý do của hiệu ứng này rõ ràng là tự động biên dịch. Mặt khác, nhận xét về các thuộc tính của các chức năng liên quan vẫn còn hiệu lực và tôi hy vọng không nên có bất kỳ loại hiểu lầm nào. – Artes

3

Những câu trả lời trên Apply[] là chỗ trên, và là điều đúng đắn nên làm, nhưng những gì bạn đang cố gắng để làm, là để thay thế một đầu List[] với một cái đầu Sequence[], ví dụ: List[List[3,5],List[6,7]] nên trở thành List[Sequence[3,5],Sequence[6,7]].

Đầu chuỗi là thứ tự nhiên vẫn còn nếu đầu của bất kỳ danh sách tham số nào bị xóa, vì vậy, Delete[Plus[3,5],0]Delete[{3,5},0]Delete[List[3,5],0] tất cả sẽ tạo ra Sequence[3,5].

Vì vậy, [email protected][#,0]&/@{{a, b}, {c, d}, {e, f}} sẽ cung cấp cho bạn giống như [email protected]@@{{a, b}, {c, d}, {e, f}}.

Hoặc, foo[#/.List->Sequence]&/@{{a, b}, {c, d}, {e, f}} cũng làm như vậy.

+1

Tôi phải không đồng ý với tuyên bố rằng anh ta muốn chuyển 'List [List [...] ..]' thành 'List [Sequence [...] ..]'. Chính xác hơn, anh ta muốn 'List [f [...] ..]', tức là anh ta muốn thay đổi phần đầu của các danh sách bên trong thành 'f'. – rcollyer

+0

Tôi đồng ý rằng đây là điều cuối cùng anh ấy "muốn". Tôi muốn nói nó theo nghĩa "những gì bạn muốn làm để đạt được điều đó ..." ;-) Xin lỗi vì sự nhầm lẫn. Để có được 'Danh sách [f [Trình tự [...]], ...] 'anh ta cần một cách để chuyển đổi một danh sách các danh sách thành một danh sách các chuỗi. Áp dụng nó trong nội bộ. –

Các vấn đề liên quan