2016-09-12 2 views
5

मेरे पास एक परिदृश्य है जहां मानक List.groupBy फ़ंक्शन वह नहीं है जो मैं चाहता हूं, लेकिन मुझे इस फ़ंक्शन के लिए सही नाम नहीं पता है, इसलिए यह खोजना मुश्किल हो रहा है।बार-बार ले जाने के बराबर कॉल करते समय कॉल: क्या इस फ़ंक्शन में "मानक" नाम होता है?

मेरे पास 'T, और 'T -> 'k कुंजी-उत्पादक फ़ंक्शन के प्रकार की एक सूची है। आइटम सूची में कुछ हद तक "समूहित" हैं, ताकि जब आप कुंजी फ़ंक्शन के माध्यम से सूची को मैप करते हैं, तो इसके परिणाम में कई बार पंक्ति में एक ही कुंजी होगी, उदा। [1; 1; 1; 2; 2; 1; 1; 3; 3; 3; 1; 1]। मैं चाहता हूं कि सूचियों की एक सूची प्राप्त करें, जहां आंतरिक सूची में वे सभी आइटम होते हैं जिनके लिए कुंजी-उत्पादक फ़ंक्शन एक ही मान देता है - लेकिन इसे 1 के अलग-अलग अनुक्रमों को समूहबद्ध नहीं करना चाहिए।

दूसरे शब्दों में, मेरा डेटा तारों की एक सूची थी, और कुंजी उत्पादक समारोह String.length था। तो इनपुट है:

["a"; "e"; "i"; "to"; "of"; "o"; "u"; "and"; "for"; "the"; "I"; "O"] 

उत्पादन मैं तलाश कर रहा हूँ होगा:

[["a"; "e"; "i"]; ["to"; "of"]; ["o"; "u"]; ["and"; "for"; "the"]; ["I"; "O"]] 

यह का एक और तरीका लगता है करने के लिए: इस सूची के पहले आइटम ले रहे हैं और परिणाम के भंडारण की तरह है कुंजी समारोह बुलाओ। फिर आप पहले सेगमेंट उत्पन्न करने के लिए takeWhile (fun x -> keyFun x = origKeyFunResult) का उपयोग करेंगे। फिर जब takeWhile वापस लौटने वाले मूल्यों को रोकता है, तो जब आप इसे रोकते हैं तो रिकॉर्ड करते हैं, और keyFun x का मान उस प्रथम मान पर है जो मूल परिणाम नहीं लौटाता है - और वहां से आगे बढ़ता है। (सिवाय इसके कि वह ओ (एन * एम) होगा जहां एम अनुक्रमों की संख्या है, और कई मामलों में ओ (एन^2) में भंग हो जाएगा - जबकि ओ (एन) समय में इस कार्य को लागू करना संभव होना चाहिए)।

अब, मैं उस समारोह को बहुत आसानी से लिख सकता हूं। यह सवाल नहीं है। मैं यह जानना चाहता हूं कि इस फ़ंक्शन के लिए मानक नाम है या नहीं। क्योंकि मैंने सोचा था कि इसे groupBy कहा जाएगा, लेकिन यह कुछ और है। (List.groupBy String.length[(1, ["a"; "e"; "i"; "o"; "u"; "I"; "O"]); (2, ["to"; "of"]), (3, ["and"; "for"; "the"])] लौटाएगा, लेकिन इस मामले में जो मैं चाहता हूं वह "ए/ई/आई", "ओ/यू", और "आई/ओ" सूचियों को अलग रहने के लिए है, और मुझे वह मूल्य नहीं चाहिए आउटपुट डेटा में होने वाली कुंजी-उत्पन्न रिटर्न)।

शायद इस फ़ंक्शन के लिए मानक नाम नहीं है। लेकिन अगर वहाँ है, तो यह क्या है?

+1

मुझे नहीं लगता कि वहाँ एक मानक है नाम। आपको आगे बढ़ना चाहिए और इसे लिखना चाहिए; आपने पहले ही कहा है कि लिखना आसान है, और फ़ंक्शन के लिए जो कोड आप लिखते हैं वह दस्तावेज करने के लिए काम करेगा जो यह करता है। –

+0

इसे गणित में 'गदरबी' कहा जाता है, जिसमें कुछ हद तक कार्यात्मक जड़ें होती हैं। – s952163

+0

मेरे अनुभव में इस समारोह को 'स्प्लिट' नाम दिया गया था। यह तारों पर विभाजित कार्य को संदर्भित करता है जो समान काम करता है। –

उत्तर

0

मुझे थोड़ी देर हो चुकी है और ऐसा लगता है कि आपको एक समाधान मिला है, और ऐसा लगता है कि एक समारोह नहीं है I F # जो समस्या को संभाल सकता है।

बस चुनौती के लिए मैं कुछ प्रयोग करने योग्य समाधान खोजने की कोशिश की और साथ आया निम्नलिखित (चाहे वे कुशल हैं या नहीं है पाठक तय करने के लिए):

open System 

module List = 
    /// <summary> 
    /// Generic List Extension: 
    /// Given a comparer function the list will be chunked into sub lists 
    /// starting when ever comparer finds a difference. 
    /// </summary> 
    let chunkByPredicate (comparer : 'T -> 'T -> bool) list = 
    let rec func (i : int, lst : 'T list) : 'T list list = 
     if i >= lst.Length then 
     List.empty 
     else 
     let first = lst.[i] 
     let chunk = lst |> List.skip(i) |> List.takeWhile (fun s -> comparer first s) 
     List.append [chunk] (func((i + chunk.Length), lst)) 

    func (0, list) |> List.where (fun lst -> not (List.isEmpty lst)) 

// 1. Using List.fold to chunk by string length 
let usingListFold (data : string list) = 
    printfn "1. Using List.fold: " 
    data 
    |> List.fold (fun (acc : string list list) s -> 
        if acc.Length > 0 then 
        let last = acc.[acc.Length - 1] 
        let lastLength = last.[0].Length 
        if lastLength = s.Length then 
         List.append (acc |> List.take (acc.Length - 1)) [(last |> List.append [s])] 
        else 
         List.append acc [[s]] 
        else 
        [[s]]) ([]) 

    |> List.iter (printfn "%A") 
    printfn "" 

// 2. Using List.chunkByPredicate 
let usingListChunkByPredicate<'a> (predicate : 'a -> 'a -> bool, data : 'a list) = 
    printfn "2. Using List.chunkByPredicate: " 
    data 
    |> List.chunkByPredicate predicate 
    |> List.iter (printfn "%A") 
    printfn "" 

[<EntryPoint>] 
let main argv = 
    let data = ["a"; "e"; "i"; "to"; "of"; "o"; "u"; "and"; "for"; "the"; "I"; "O"] 

    usingListFold data 
    usingListChunkByPredicate<string>((fun first s -> first.Length = s.Length), data) 

    let intData = [0..50] 
    usingListChunkByPredicate<int>((fun first n -> first/10 = n/10), intData) 

    Console.ReadLine() |> ignore 
    0 
संबंधित मुद्दे