2009-06-01 18 views
6

साथ नंबरों की सूची मैं #एफ #

मैं नंबरों की सूची की कार्तीय उत्पादों की गणना करने की कोशिश कर रहा हूँ करने के लिए नया हूँ की कार्तीय उत्पाद गिना जा रहा है। मैंने इसे "उधार लिया"।

let xs = [1..99] 
let ys = [1..99] 
seq {for x in xs do for y in ys do yield x * y} 

क्या कोई बेहतर या अधिक सुरुचिपूर्ण तरीका है?

गैरी

+0

संबंधित प्रश्न यहां: http://stackoverflow.com/questions/482866/f-cross-product-of-two-lists – Benjol

उत्तर

9

एक और possibiltiy सूची मॉड्यूल द्वारा प्रदान किया जाएगा कार्यक्षमता के आधार पर समस्या से निपटने के लिए:

let xs = [1..99] 
let ys = [1..99] 
let zs = xs |> List.collect (fun x -> ys |> List.map (fun y -> x*y)) 

जो .concat करने के लिए अतिरिक्त कॉल से बचा जाता है और यह भी काम करना चाहिए।

लेकिन मैं आपके समाधान के साथ रहना चाहता हूं। यह सबसे पठनीय होना चाहिए जो असली मैच विजेता है। (बस कोड को ज़ोर से पढ़ने की कोशिश करें। आपका पूरी तरह समझ में आता है और नोडोरिन या मेरा नहीं हैं।)

+1

आह, मैं सोच रहा था कि 'मैपकॉनकैट' विधि कहाँ गई थी! ऐसा लगता है कि इसे अभी तक नवीनतम संस्करण में 'संग्रह' करने के लिए बदल दिया गया था। – Noldorin

+0

हमारे प्रत्येक समाधान के बारे में समझने योग्य/पठनीय होने के संबंध में, मुझे लगता है कि यह कुछ हद तक व्यक्तिपरक है। हमने निश्चित रूप से अधिक सामान्य रूप से "कार्यात्मक" शैली समाधान प्रदान किए हैं, जबकि ओपी ने एक (पूरी तरह से अच्छा) समाधान सुझाया है जो आम तौर पर "अनिवार्य" संरचनाओं का उपयोग करता है। मुझे संदेह है कि किसी कार्यात्मक पृष्ठभूमि से किसी को हमारी विधियों में से कोई भी स्पष्ट मिलेगा। – Noldorin

2

वहाँ वास्तव में है एक थोड़ा और अधिक सुरुचिपूर्ण तरीका (कम से कम कार्यात्मक अर्थ में) जो कार्यों कि List वर्ग के भीतर मौजूद उपयोग करता है, कार्तीय उत्पादों की गणना करने के। (वहाँ दृश्यों को शामिल करने की कोई जरूरत कम से कम सीधे नहीं है या यहाँ लूप होता है,।)

इस प्रयास करें:

let xs = [1..99] 
let ys = [1..99] 
xs |> List.map(fun x -> ys |> List.map(fun y -> x * y)) |> List.concat 

थोड़ा लंबा बेशक, हालांकि अधिक शैली में कार्यात्मक, यह प्रतीत होता है।

+1

वास्तव में प्रश्न में कोड आपके कोड की तुलना में एक सूची समझ के करीब है, मेरी राय में । आपका एक सूची समझ के desugared संस्करण की तरह है। –

+0

हाँ, मेरा मतलब सूची समझ वास्तव में नहीं था - मुझे यकीन नहीं है कि इसके लिए एक विशेष नाम है, लेकिन मेरा मतलब सूची है। * फ़ंक्शंस। – Noldorin

+0

क्या आप "अनुक्रमों को शामिल करने की कोई आवश्यकता नहीं है" के बारे में विस्तार से बता सकते हैं, मुझे समझ में नहीं आता कि Seq.map पर List.map का उपयोग करने के लाभ क्या हैं? – ninegrid

7

अस्वीकरण: मेरे पास वर्तमान F # स्थापित मशीन नहीं है, इसलिए मैं अपने कोड का परीक्षण नहीं कर सकता। असल में, हालांकि, अगर आप हास्केल से sequence चोरी, आप अपने कार्यक्रम के रूप में

let cartesian = sequence >> List.map product 

लिखने और

cartesian [[1..99]; [1..99]] 

यहाँ sequence लिखने का तरीका बताया गया के रूप में यह चला सकते हैं। यह आपके द्वारा लिखे अनुक्रम अभिव्यक्ति का एक सामान्य संस्करण है। यह सिर्फ असीमित संख्या में सूचियों को संभालता है: { for x in xs do for y in ys do for z in zs ... yield [x;y;z;...] }

let rec sequence = function 
    | [] -> Seq.singleton [] 
    | (l::ls) -> seq { for x in l do for xs in sequence ls do yield (x::xs) } 
// also you'll need product to do the multiplication 
let product = Seq.fold_left1 (*) 

तो फिर आप अपने प्रोग्राम लिख सकते हैं के रूप में

let cartesian xs ys = [xs; ys] |> sequence |> List.map product 
// ... or one-argument, point-free style: 
let cartesian' = sequence >> Seq.map product 

आप List रों करने के लिए कुछ Seq रों बदलने के लिए हो सकता है।

हालांकि, आपकी गैर-सामान्य सूची समझ का अर्थ अनुमान लगाने वाले लोगों की संख्या शायद sequence नाम पहचानने से कहीं अधिक है, इसलिए आप सूची समझ के साथ शायद बेहतर हो सकते हैं। sequence किसी भी समय आप गणना गणनाओं की एक पूरी सूची चलाने के लिए काम में आता है, हालांकि।

+0

+1 मोनैड को आमंत्रित करने के लिए +1 –

+0

आप देखेंगे कि मैंने "monad" कहने से परहेज किया है। "गणना गणना" अभी भी "गर्म अस्पष्ट चीज़" के रूप में अनुकूल नहीं है, हालांकि। :) –