2010-09-20 10 views
5

मैं अगर यह उद्धृत किया गया है एक स्ट्रिंग FSharp का उपयोग कर के मध्य भाग को निकालने के लिए, इस तरह समान हैं:मैं FSharp में स्ट्रिंग के मध्य भाग को कैसे निकाल सकता हूं?

let middle = 
    match original with 
    | "\"" + mid + "\"" -> mid 
    | all -> all 

लेकिन यह इन्फ़िक्स ऑपरेटर की + पैटर्न अभिव्यक्ति में क्योंकि काम नहीं करता। मैं इसे कैसे निकाला जा सकता हूं?

+0

यह भी देखें http://stackoverflow.com/questions/3722591/pattern-matching-on-the-beginning- ऑफ-ए-स्ट्रिंग-इन-एफ – Brian

उत्तर

10

मुझे नहीं लगता कि इसके लिए कोई सीधा समर्थन है, लेकिन आप निश्चित रूप से सक्रिय पैटर्न लिख सकते हैं। सक्रिय पैटर्न आपको अपना कोड लागू करने की अनुमति देते हैं जो पैटर्न मिलान के हिस्से के रूप में चलाएगा और आप & मूल्य के कुछ हिस्से को निकाल सकते हैं।

निम्नलिखित एक पैटर्न है जो दो पैरामीटर (उपसर्ग और पोस्टफिक्स स्ट्रिंग) लेता है और यदि निर्दिष्ट इनपुट निर्दिष्ट स्ट्रिंग के साथ दिया गया इनपुट समाप्त होता है तो समाप्त होता है। पैटर्न पूरा नहीं हुआ है (असफल हो सकता है), इसलिए हम |Name|_| सिंटैक्स का उपयोग करें और यह विकल्प मान देने के लिए की आवश्यकता होगी:

let (|Middle|_|) prefix postfix (input:string) = 
    // Check if the string starts with 'prefix', ends with 'postfix' and 
    // is longer than the two (meaning that it contains some middle part) 
    if input.StartsWith(prefix) && input.EndsWith(postfix) && 
    input.Length >= (prefix.Length + postfix.Length) then 
    // Strip the prefix/postfix and return 'Some' to indicate success 
    let len = input.Length - prefix.Length - postfix.Length 
    Some(input.Substring(prefix.Length, len)) 
    else None // Return 'None' - string doesn't match the pattern 

अब हम पैटर्न में Middle उपयोग कर सकते हैं मिलान (उदाहरण के लिए जब match उपयोग करते हुए):

match "[aaa]" with 
| Middle "[" "]" mid -> mid 
| all -> all 
+0

आपकी कार्यान्वयन रणनीति मेरी तुलना में बेहतर है (केवल 'सबस्ट्रिंग' पर एक कॉल), लेकिन यह देखने में खुशी हुई कि हमारे पास एक ही विचार था! :) – Brian

+0

धन्यवाद टॉमस। आपका जवाब इतना स्पष्ट और सहायक है। ब्रायन और केवीबी के लिए भी धन्यवाद। दुर्भाग्यवश, मैं स्टैक ओवरफ्लो में नया हूं और आपके जवाब देने के लिए क्रेडिट क्रेडिट नहीं है। – newwave

+0

@ ब्रायन: हाँ, ऐसा लगता है कि हमने लगभग एक ही जवाब पोस्ट किया है! मैंने आपकी रणनीति भी मानी (लेकिन सोचा कि जांच की लंबाई आसान है) और मैंने टुपल का उपयोग करके दो तर्कों को पारित करने पर भी विचार किया :-) –

2

पैटर्न में सीमित व्याकरण है - आप किसी भी अभिव्यक्ति का उपयोग नहीं कर सकते हैं। इस मामले में, मैं सिर्फ एक का उपयोग करते हैं/तो/बाकी:

let middle (s:string) = 
    if s.[0] = '"' && s.[s.Length - 1] = '"' && s.Length >= 2 then 
    s.Substring(1,s.Length - 2) 
    else s 

तो स्थिर में जाना जाता है शुरुआत और अंत के साथ एक स्ट्रिंग के बीच हथियाने कुछ है कि आप एक बहुत करूँगा है, तो आप हमेशा कर सकते हैं टॉमस सुझाव के रूप में एक सक्रिय पैटर्न का उपयोग करें।

+0

धन्यवाद kvb। मैं टॉमस का जवाब सिर्फ इसलिए पसंद करता हूं क्योंकि मैं अनिवार्य तरीके से उपयोग नहीं करना चाहता हूं। – newwave

3

बचाव के लिए पैरामीटर active patterns!

let (|HasPrefixSuffix|_|) (pre:string, suf:string) (s:string) = 
    if s.StartsWith(pre) then 
     let rest = s.Substring(pre.Length) 
     if rest.EndsWith(suf) then 
      Some(rest.Substring(0, rest.Length - suf.Length)) 
     else 
      None 
    else 
     None 

let Test s = 
    match s with 
    | HasPrefixSuffix("\"","\"") inside -> 
     printfn "quoted, inside is: %s" inside 
    | _ -> printfn "not quoted: %s" s 

Test "\"Wow!\"" 
Test "boring" 
+1

पैरामीटरेटेड सक्रिय पैटर्न आश्चर्यजनक रूप से शक्तिशाली हैं। – gradbot

+0

गंभीरता से निफ्टी! :-) –

2

... या बस का उपयोग सादे पुराने नियमित अभिव्यक्ति

let Middle input = 
    let capture = Regex.Match(input, "\"([^\"]+)\"") 
    match capture.Groups.Count with 
    | 2 -> capture.Groups.[1].Value 
    | _ -> input 
+0

एक विकल्प प्रकार वापस करने के लिए बेहतर हो सकता है? –

+0

लेखक पूरी स्ट्रिंग को वापस करना चाहता है अगर इसे उद्धृत नहीं किया गया है, क्योंकि मैं प्रश्न समझ गया था। –

0

सुनिश्चित नहीं हैं कि यह कैसे कुशल है:

let GetQuote (s:String) (q:char) = 
     s 
     |> Seq.skip ((s |> Seq.findIndex (fun c -> c = q))+1) 
     |> Seq.takeWhile (fun c-> c <> q) 
     |> Seq.fold(fun acc c -> String.Format("{0}{1}", acc, c)) "" 

या वहां गुना के स्थान पर सबस्ट्रिंग के साथ इस है:

let GetQuote2 (s:String) (q:char) = 
    let isQuote = (fun c -> c = q) 
    let a = (s |> Seq.findIndex isQuote)+1 
    let b = ((s |> Seq.take(a) |> Seq.findIndex isQuote)-1) 
    s.Substring(a,b); 

ये मिलेगा स्ट्रिंग में कहीं भी उद्धृत पाठ का पहला उदाहरण उदाहरण के लिए "हैलो [वर्ल्ड]" -> "वर्ल्ड"

संबंधित मुद्दे