कैसे करें वन-लाइनर अगर और स्टेटमेंट?


104

क्या मैं गो (गोलंग) में चर असाइनमेंट के साथ एक साधारण इफ-स्टेटमेंट लिख सकता हूं जैसा कि मैं php में करूंगा? उदाहरण के लिए:

$var = ( $a > $b )? $a: $b;

वर्तमान में मुझे निम्नलिखित का उपयोग करना है:

var c int
if a > b {
    c = a
} else {
    c = b
}

क्षमा करें, यदि यह नियंत्रण कथन है और मुझे जानकारी इन-साइट या Google खोज के माध्यम से नहीं मिल रही है तो मुझे नाम याद नहीं है। : /


4
इसका एक टर्नरी ऑपरेटर कहा जाता है ... और नहीं, गो एक नहीं है।
साइमन व्हाइटहेड

6
मेरा मानना ​​है कि आप जिस शब्द की तलाश कर रहे हैं, वह "टर्नेरी" है
बेंजामिन


10
बस स्पष्ट करने के लिए, एक टर्नरी ऑपरेटर, एरिटी 3 का कोई भी ऑपरेटर है, वह कोई भी ऑपरेटर है जो 3 उप-अभिव्यक्तियों को बांधता है। C के पास केवल एक ही ऑपरेटर होता है। इसलिए इसे आमतौर पर टर्नरी ऑपरेटर कहा जाता है। इसका असली नाम "सशर्त ऑपरेटर" है, हालांकि।
thwd

जवाबों:


131

जैसा कि टिप्पणी में कहा गया है, गो टर्नरी वन लाइनर्स का समर्थन नहीं करता है। सबसे छोटा रूप मैं यह सोच सकता हूं:

var c int
if c = b; a > b {
    c = a
}

लेकिन कृपया ऐसा न करें, यह इसके लायक नहीं है और केवल उन लोगों को भ्रमित करेगा जो आपके कोड को पढ़ते हैं।


83
@thoroc मैं वास्तव में वास्तविक जीवन में इससे बचना चाहूंगा, क्योंकि यह गैर सहज IMHO है, यह कम पठनीयता के लिए 2 लाइनों को बचाने के लायक नहीं है।
Not_a_Golfer

14
@thoroc, कृपया नोट करें कि Not_a_Golfer ने क्या कहा। आपको बनाए रखने योग्य सॉफ़्टवेयर लिखने का प्रयास करना चाहिए, न कि खुद को दिखावा करना चाहिए। नीट के ट्रिक साफ-सुथरे हैं लेकिन आपका कोड (अगले कुछ महीनों / वर्षों में आप सहित) पढ़ने वाला अगला लड़का उनकी सराहना नहीं करेगा।
कोस्टिक्स

3
यह निर्भर करता है, जहाँ तक पठनीयता। मुझे लगता है कि यह अधिक पठनीय है, लेकिन किसी भी चीज की तरह, इसका दुरुपयोग किया जा सकता है। यदि आपको एक वैरिएबल घोषित करने की आवश्यकता है जो कि अगर ब्लॉक के बाहर की आवश्यकता नहीं है, तो मुझे लगता है कि यह एक विजेता है।
अरबाजबार

@Not_a_Golfer यह केवल समरूपता द्वारा पठनीयता नहीं है, इरादे के संरचनात्मक विपरीत संकलित कोड में भी है, कभी-कभी एक अतिरेक आरंभीकरण के लिए अतिरिक्त लागत के साथ भी।
वुल्फ

5
ओह, आनंद, देखिए कि टर्नरी ऑपरेटर नहीं होने से कितना फायदा हुआ। किए गए पठनीयता टिप्पणियों के अलावा, आपने एक आलसी-मूल्यांकन किए गए निर्माण को बदल दिया है जहां केवल एक शाखा को कभी भी चलाया जाता है जहां पहला हमेशा चलता है और दूसरा इसके अतिरिक्त चलाया जा सकता है।
7

29

मैं अक्सर निम्नलिखित का उपयोग करता हूं:

c := b
if a > b {
    c = a
}

मूल रूप से @ Not_a_Golfer के समान लेकिन प्रकार के अनुमान का उपयोग करते हुए ।


4
उसी कमी के साथ: आप स्पष्ट रूप से सममित आवश्यकता के लिए एक असममित समाधान का उपयोग करते समय समझ को जटिल करते हैं।
वुल्फ

2
और एक ही समय में दो शाखाओं में से केवल एक शाखा का उपयोग किया जाना चाहिए, जहां कभी भी एक का मूल्यांकन किया जाएगा, कभी-कभी दोनों (जिस मामले में पहला मूल्यांकन निरर्थक था)
इसकी शानदार गति

1
उपयोग-मामले के आधार पर, यह अभी भी बहुत उपयोगी हो सकता है। जैसे listeningPath := "production.some.com"; if DEBUG { listeningPath := "development.some.com" }उत्पादन के लिए त्रिगुट के रूप में एक ही गति, और imho बहुत अच्छी पठनीयता।
लेविट

मैं आमतौर पर रोता हूं जब जानबूझकर सीपीयू चक्र बर्बाद होता है।
अलसीसावी

28

जैसा कि दूसरों ने उल्लेख किया है, Goटर्नरी वन-लाइनर्स का समर्थन नहीं करता है। हालांकि, मैंने एक उपयोगिता फ़ंक्शन लिखा है जो आपको जो चाहें प्राप्त करने में मदद कर सकता है।

// IfThenElse evaluates a condition, if true returns the first parameter otherwise the second
func IfThenElse(condition bool, a interface{}, b interface{}) interface{} {
    if condition {
        return a
    }
    return b
}

यहां कुछ परीक्षण मामले दिखाए गए हैं कि आप इसका उपयोग कैसे कर सकते हैं

func TestIfThenElse(t *testing.T) {
    assert.Equal(t, IfThenElse(1 == 1, "Yes", false), "Yes")
    assert.Equal(t, IfThenElse(1 != 1, nil, 1), 1)
    assert.Equal(t, IfThenElse(1 < 2, nil, "No"), nil)
}

मनोरंजन के लिए, मैंने और उपयोगी उपयोगिताएँ लिखी हैं जैसे:

IfThen(1 == 1, "Yes") // "Yes"
IfThen(1 != 1, "Woo") // nil
IfThen(1 < 2, "Less") // "Less"

IfThenElse(1 == 1, "Yes", false) // "Yes"
IfThenElse(1 != 1, nil, 1)       // 1
IfThenElse(1 < 2, nil, "No")     // nil

DefaultIfNil(nil, nil)  // nil
DefaultIfNil(nil, "")   // ""
DefaultIfNil("A", "B")  // "A"
DefaultIfNil(true, "B") // true
DefaultIfNil(1, false)  // 1

FirstNonNil(nil, nil)                // nil
FirstNonNil(nil, "")                 // ""
FirstNonNil("A", "B")                // "A"
FirstNonNil(true, "B")               // true
FirstNonNil(1, false)                // 1
FirstNonNil(nil, nil, nil, 10)       // 10
FirstNonNil(nil, nil, nil, nil, nil) // nil
FirstNonNil()                        // nil

यदि आप इनमें से किसी का भी उपयोग करना चाहते हैं, तो आप उन्हें यहां पा सकते हैं https://github.com/shomali11/util


12

सही उत्तर की ओर इशारा करने के लिए धन्यवाद।

मैंने सिर्फ गोलंग FAQ (duh) की जाँच की है और यह स्पष्ट रूप से बताता है, यह भाषा में उपलब्ध नहीं है:

क्या गो के पास है ?: ऑपरेटर?

गो में कोई टर्नरी फॉर्म नहीं है। आप समान परिणाम प्राप्त करने के लिए निम्नलिखित का उपयोग कर सकते हैं:

if expr {
    n = trueVal
} else {
    n = falseVal
}

अतिरिक्त जानकारी मिली कि विषय पर ब्याज हो सकता है:


यह एक पंक्ति में भी संभव है var c int; if a > b { c = a } else { c = b }:? लेकिन मैं इसे पाठक के मनोरंजन के लिए एक हल्का ब्लॉक बनाने के लिए 5 लाइनों में रखने का सुझाव
वुल्फ

7

एक नक्शे का उपयोग करके केवल एक लाइन में ऐसा करने का एक संभव तरीका, सरल मैं जाँच रहा हूं कि a > bक्या यह trueमैं अन्यथा करने के cलिए असाइन कर रहा हूंab

c := map[bool]int{true: a, false: b}[a > b]

हालाँकि, यह आश्चर्यजनक लग रहा है, लेकिन कुछ मामलों में मूल्यांकन आदेश के कारण यह सही समाधान नहीं हो सकता है। उदाहरण के लिए, यदि मैं जाँच कर रहा हूँ कि क्या किसी वस्तु को nilउसमें से कुछ संपत्ति नहीं मिली है, तो निम्नलिखित कोड स्निपेट देखें, जो panicमामले में होगाmyObj equals nil

type MyStruct struct {
   field1 string
   field2 string 
}

var myObj *MyStruct
myObj = nil 

myField := map[bool]string{true: myObj.field1, false: "empty!"}[myObj != nil}

क्योंकि मानचित्र का निर्माण और स्थिति के मूल्यांकन से पहले पहले बनाया myObj = nilजाएगा , इस मामले में बस घबराहट होगी।

यह उल्लेख करना न भूलें कि आप अभी भी शर्तों को केवल एक सरल लाइन में कर सकते हैं, निम्नलिखित की जांच करें:

var c int
...
if a > b { c = a } else { c = b}

4

टेम्बरी ऑपरेटर के बजाय लैम्ब्डा फ़ंक्शन का उपयोग करें

उदाहरण 1

अधिकतम int देने के लिए

package main

func main() {

    println( func(a,b int) int {if a>b {return a} else {return b} }(1,2) )
}

उदाहरण 2

मान लीजिए कि must(err error)त्रुटियों को संभालने के लिए आपके पास यह फ़ंक्शन है और आप एक शर्त पूरी नहीं होने पर इसका उपयोग करना चाहते हैं। (आनंद लें https://play.golang.com/p/COXyo0qIslP )

package main

import (
    "errors"
    "log"
    "os"
)

// must is a little helper to handle errors. If passed error != nil, it simply panics.
func must(err error) {
    if err != nil {
        log.Println(err)
        panic(err)
    }
}

func main() {

    tmpDir := os.TempDir()
    // Make sure os.TempDir didn't return empty string
    // reusing my favourite `must` helper
    // Isn't that kinda creepy now though?
    must(func() error {
        var err error
        if len(tmpDir) > 0 {
            err = nil
        } else {
            err = errors.New("os.TempDir is empty")
        }
        return err
    }()) // Don't forget that empty parentheses to invoke the lambda.
    println("We happy with", tmpDir)
}

2
दिलचस्प दृष्टिकोण, यह अधिक जटिल मामलों में उपयोगी हो सकता है। :)
वक्रोच

1

कभी-कभी, मैं एक ही पंक्ति में होने और परिभाषित करने के लिए अनाम फ़ंक्शन का उपयोग करने का प्रयास करता हूं। नीचे की तरह:

a, b = 4, 8

c := func() int {
    if a >b {
      return a
    } 
    return b
  } ()

https://play.golang.org/p/rMjqytMYeQ0


0

एक बहुत ही समान निर्माण भाषा में उपलब्ध है

**if <statement>; <evaluation> {
   [statements ...]
} else {
   [statements ...]
}*

*

अर्थात

if path,err := os.Executable(); err != nil {
   log.Println(err)
} else {
   log.Println(path)
}

0

आप इसके लिए एक क्लोजर का उपयोग कर सकते हैं:

func doif(b bool, f1, f2 func()) {
    switch{
    case b:
        f1()
    case !b:   
        f2()
    }
}

func dothis() { fmt.Println("Condition is true") }

func dothat() { fmt.Println("Condition is false") }

func main () {
    condition := true
    doif(condition, func() { dothis() }, func() { dothat() })
}

गो में क्लोजर सिंटैक्स के साथ मेरे पास केवल एक पकड़ है डिफ़ॉल्ट शून्य पैरामीटर शून्य रिटर्न फ़ंक्शन के लिए कोई अन्य नहीं है, तो यह बहुत अच्छा होगा (जैसे आप केवल एक प्रकार के नाम के साथ नक्शा, सरणी और स्लाइस शाब्दिक कैसे घोषित करते हैं)।

या यहां तक ​​कि छोटे संस्करण, एक टिप्पणीकार के रूप में सुझाव दिया:

func doif(b bool, f1, f2 func()) {
    switch{
    case b:
        f1()
    case !b:   
        f2()
    }
}

func dothis() { fmt.Println("Condition is true") }

func dothat() { fmt.Println("Condition is false") }

func main () {
    condition := true
    doif(condition, dothis, dothat)
}

यदि आपको फ़ंक्शन को पैरामीटर देने की आवश्यकता है, तो आपको अभी भी एक बंद का उपयोग करने की आवश्यकता होगी। यह मेरे द्वारा किए जाने वाले कार्यों के बजाय पारित होने के तरीकों के मामले में माना जा सकता है, जहां पैरामीटर विधियों से जुड़ी संरचना है।


छोटा संस्करणdoif(condition, dothis, dothat)
वेल्लोटिस

1
हाँ, यह और भी छोटा होगा, केवल कार्य कर रहा है। केवल एक उपयोगिता पुस्तकालय में एक बार इस फ़ंक्शन का होना आवश्यक है, और आप इसे अपने कोड के माध्यम से उपयोग कर सकते हैं।
लौकी सुमिरन्या
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.