2014-10-13 39 views
8

में नलिका या खाली सूची को संभालने का बेवकूफ तरीका कहें कि मेरे पास प्रकार का एक चर activities है। अगर सूची शून्य नहीं है और खाली नहीं है, तो मैं कुछ करना चाहता हूं, अन्यथा मैं कुछ और करना चाहता हूं। मैं निम्नलिखित समाधान के साथ आया:कोटलिन

when { 
    activities != null && !activities.empty -> doSomething 
    else -> doSomethingElse 
} 

क्या कोटलिन में ऐसा करने का एक और बेवकूफ तरीका है? आप वास्तव में व्यवहार आप वर्णित मुझे लगता है कि अपने संस्करण बेहतर तो किसी और अधिक संक्षिप्त कुछ भी मैं के बारे में सोच सकते हैं पढ़ता चाहते हैं

+1

नोट: एक 'when' दो विकल्पों के साथ बहुत एक सामान्य' –

उत्तर

11

कुछ सरल क्रियाओं आप सुरक्षित कॉल ऑपरेटर का उपयोग कर सकते हैं के लिए, कार्रवाई मानते हुए भी एक खाली सूची पर काम नहीं सम्मान करता है (के अपने मामले को संभालने के लिए दोनों बातिल और खाली:

myList?.forEach { ...only iterates if not null and not empty } 

अन्य कार्यों के लिए आप एक विस्तार समारोह लिख सकते हैं - अगर आप this रूप में या एक पैरामीटर के रूप में सूची प्राप्त करना चाहते हैं के आधार पर दो रूपों:।

+०१२३५१६४१०६
inline fun <E: Any, T: Collection<E>> T?.withNotNullNorEmpty(func: T.() -> Unit): Unit { 
    if (this != null && this.isNotEmpty()) { 
     with (this) { func() } 
    } 
} 

inline fun <E: Any, T: Collection<E>> T?.whenNotNullNorEmpty(func: (T) -> Unit): Unit { 
    if (this != null && this.isNotEmpty()) { 
     func(this) 
    } 
} 

कौन सा आप उपयोग कर सकते हैं:

inline fun <E: Any, T: Collection<E>> T?.withNullOrEmpty(func:() -> Unit): Unit { 
    if (this == null || this.isEmpty()) { 
     func() 
    } 
} 

मैं क्योंकि तब आप कुछ के साथ एक if या when बयान बदल रहे हैं इन चेनिंग से बचने होगा:

fun foo() { 
    val something: List<String>? = makeListOrNot() 
    something.withNotNullNorEmpty { 
     // do anything I want, list is `this` 
    } 

    something.whenNotNullNorEmpty { myList -> 
     // do anything I want, list is `myList` 
    } 
} 

तुम भी उलटा समारोह कर सकते हैं अधिक शब्दशः और आप इस क्षेत्र में और अधिक हो रहे हैं कि नीचे दिए गए विकल्पों को प्रदान करते हैं, जो सफलता/विफलता स्थितियों के लिए पूर्ण शाखा है।

नोट: इन एक्सटेंशन को Collections के सभी वंशजों को गैर शून्य मान रखने के लिए सामान्यीकृत किया गया था। और सिर्फ सूचियों से अधिक के लिए काम करते हैं।

विकल्प:

Kotlin के लिए Result पुस्तकालय के अपने मामले को संभालने के लिए एक अच्छा तरीका देता है "ऐसा करते हैं, या कि" प्रतिक्रिया मूल्यों पर आधारित। वादे के लिए, आप Kovenant लाइब्रेरी में एक ही चीज़ पा सकते हैं।

इन दोनों पुस्तकालयों में आपको एक ही समारोह से वैकल्पिक परिणामों को वापस करने के लिए और परिणाम के आधार पर कोड को ब्रांच करने के तरीके भी मिलते हैं। उन्हें आवश्यकता है कि आप "उत्तर" के प्रदाता को नियंत्रित कर रहे हैं जिस पर कार्य किया जाता है।

ये Optional और Maybe के लिए कोटिन विकल्प अच्छे हैं।

तलाश इसके अलावा (और शायद बहुत ज्यादा) विस्तार कार्य

यह खंड सिर्फ इतना है कि जब आप सवाल यहां उठाए गए जैसे एक मुद्दा मारा, आप आसानी से बहुत-से उत्तर Kotlin में बनाने के लिए मिल सकता है दिखाने के लिए है जिस तरह से आप चाहते हैं उसे कोडिंग करना। अगर दुनिया पसंद नहीं है, तो दुनिया को बदलें। यह एक अच्छा या बुरा जवाब के रूप में नहीं है, बल्कि अतिरिक्त जानकारी के रूप में है।

आप विस्तार कार्यों की तरह है और उन्हें एक अभिव्यक्ति में चेनिंग पर विचार करना चाहते हैं, तो मैं शायद उन्हें बदल जाएगा इस प्रकार है ...

withXyz जायके this वापस जाने के लिए और whenXyz की इजाजत दी एक नए प्रकार लौटना चाहिए पूरा संग्रह कुछ नया बनने के लिए (शायद मूल से भी असंबंधित)।

val BAD_PREFIX = "abc" 
fun example(someList: List<String>?) { 
    someList?.filterNot { it.startsWith(BAD_PREFIX) } 
      ?.sorted() 
      .withNotNullNorEmpty { 
       // do something with `this` list and return itself automatically 
      } 
      .whenNotNullNorEmpty { list -> 
       // do something to replace `list` with something new 
       listOf("x","y","z") 
      } 
      .whenNullOrEmpty { 
       // other code returning something new to replace the null or empty list 
       setOf("was","null","but","not","now") 
      } 
} 

नोट:: जैसे निम्नलिखित कोड में जिसके परिणामस्वरूप इस संस्करण के लिए पूर्ण कोड पोस्ट (1)

के अंत में है लेकिन तुम भी एक कस्टम के साथ एक पूरी तरह से नए दिशा जा सकते हैं " इस अन्यथा कि "तंत्र:

fun foo(someList: List<String>?) { 
    someList.whenNullOrEmpty { 
     // other code 
    } 
    .otherwise { list -> 
     // do something with `list` 
    } 
} 

कोई सीमा नहीं है, रचनात्मक होना और एक्सटेंशन की शक्ति जानने के लिए, नए विचारों की कोशिश, और जैसा कि आप देख सकते हैं वहाँ कैसे लोगों को इस प्रकार की स्थितियों कोड करने के लिए चाहते हैं के लिए कई बदलाव होते रहते हैं । Stdlib भ्रमित किए बिना इन प्रकार के तरीकों के 8 भिन्नताओं का समर्थन नहीं कर सकता है। लेकिन प्रत्येक विकास समूह में एक्सटेंशन हो सकते हैं जो उनकी कोडिंग शैली से मेल खाते हैं।

नोट:

: यहाँ "श्रृंखलित" संस्करण के लिए पूर्ण कोड है: इस संस्करण के लिए पूर्ण कोड पोस्ट (2)

नमूना कोड 1 के अंत में है

inline fun <E: Any, T: Collection<E>> T?.withNotNullNorEmpty(func: T.() -> Unit): T? { if (this != null && this.isNotEmpty()) { with (this) { func() } } return this } inline fun <E: Any, T: Collection<E>, R: Any> T?.whenNotNullNorEmpty(func: (T) -> R?): R? { if (this != null && this.isNotEmpty()) { return func(this) } return null } inline fun <E: Any, T: Collection<E>> T?.withNullOrEmpty(func:() -> Unit): T? { if (this == null || this.isEmpty()) { func() } return this } inline fun <E: Any, T: Collection<E>, R: Any> T?.whenNullOrEmpty(func:() -> R?): R? { if (this == null || this.isEmpty()) { return func() } return null } 

नमूना कोड 2:यहाँ एक "इस अन्यथा के लिए पूरा कोड है कि "पुस्तकालय (इकाई परीक्षण के साथ):

inline fun <E : Any, T : Collection<E>> T?.withNotNullNorEmpty(func: T.() -> Unit): Otherwise { 
    return if (this != null && this.isNotEmpty()) { 
     with (this) { func() } 
     OtherwiseIgnore 
    } else { 
     OtherwiseInvoke 
    } 
} 

inline fun <E : Any, T : Collection<E>> T?.whenNotNullNorEmpty(func: (T) -> Unit): Otherwise { 
    return if (this != null && this.isNotEmpty()) { 
     func(this) 
     OtherwiseIgnore 
    } else { 
     OtherwiseInvoke 
    } 
} 

inline fun <E : Any, T : Collection<E>> T?.withNullOrEmpty(func:() -> Unit): OtherwiseWithValue<T> { 
    return if (this == null || this.isEmpty()) { 
     func() 
     OtherwiseWithValueIgnore<T>() 
    } else { 
     OtherwiseWithValueInvoke(this) 
    } 
} 

inline fun <E : Any, T : Collection<E>> T?.whenNullOrEmpty(func:() -> Unit): OtherwiseWhenValue<T> { 
    return if (this == null || this.isEmpty()) { 
     func() 
     OtherwiseWhenValueIgnore<T>() 
    } else { 
     OtherwiseWhenValueInvoke(this) 
    } 
} 

interface Otherwise { 
    fun otherwise(func:() -> Unit): Unit 
} 

object OtherwiseInvoke : Otherwise { 
    override fun otherwise(func:() -> Unit): Unit { 
     func() 
    } 
} 

object OtherwiseIgnore : Otherwise { 
    override fun otherwise(func:() -> Unit): Unit { 
    } 
} 

interface OtherwiseWithValue<T> { 
    fun otherwise(func: T.() -> Unit): Unit 
} 

class OtherwiseWithValueInvoke<T>(val value: T) : OtherwiseWithValue<T> { 
    override fun otherwise(func: T.() -> Unit): Unit { 
     with (value) { func() } 
    } 
} 

class OtherwiseWithValueIgnore<T> : OtherwiseWithValue<T> { 
    override fun otherwise(func: T.() -> Unit): Unit { 
    } 
} 

interface OtherwiseWhenValue<T> { 
    fun otherwise(func: (T) -> Unit): Unit 
} 

class OtherwiseWhenValueInvoke<T>(val value: T) : OtherwiseWhenValue<T> { 
    override fun otherwise(func: (T) -> Unit): Unit { 
     func(value) 
    } 
} 

class OtherwiseWhenValueIgnore<T> : OtherwiseWhenValue<T> { 
    override fun otherwise(func: (T) -> Unit): Unit { 
    } 
} 


class TestBrancher { 
    @Test fun testOne() { 
     // when NOT null or empty 

     emptyList<String>().whenNotNullNorEmpty { list -> 
      fail("should not branch here") 
     }.otherwise { 
      // sucess 
     } 

     nullList<String>().whenNotNullNorEmpty { list -> 
      fail("should not branch here") 
     }.otherwise { 
      // sucess 
     } 

     listOf("a", "b").whenNotNullNorEmpty { list -> 
      assertEquals(listOf("a", "b"), list) 
     }.otherwise { 
      fail("should not branch here") 
     } 

     // when YES null or empty 

     emptyList<String>().whenNullOrEmpty { 
      // sucess 
     }.otherwise { list -> 
      fail("should not branch here") 
     } 

     nullList<String>().whenNullOrEmpty { 
      // success 
     }.otherwise { 
      fail("should not branch here") 
     } 

     listOf("a", "b").whenNullOrEmpty { 
      fail("should not branch here") 
     }.otherwise { list -> 
      assertEquals(listOf("a", "b"), list) 
     } 

     // with NOT null or empty 

     emptyList<String>().withNotNullNorEmpty { 
      fail("should not branch here") 
     }.otherwise { 
      // sucess 
     } 

     nullList<String>().withNotNullNorEmpty { 
      fail("should not branch here") 
     }.otherwise { 
      // sucess 
     } 

     listOf("a", "b").withNotNullNorEmpty { 
      assertEquals(listOf("a", "b"), this) 
     }.otherwise { 
      fail("should not branch here") 
     } 

     // with YES null or empty 

     emptyList<String>().withNullOrEmpty { 
      // sucess 
     }.otherwise { 
      fail("should not branch here") 
     } 

     nullList<String>().withNullOrEmpty { 
      // success 
     }.otherwise { 
      fail("should not branch here") 
     } 

     listOf("a", "b").withNullOrEmpty { 
      fail("should not branch here") 
     }.otherwise { 
      assertEquals(listOf("a", "b"), this) 
     } 


    } 

    fun <T : Any> nullList(): List<T>? = null 
} 
1

अगर उचित

activities?.forEach { 
    doSmth(it) 
} 

?.forEach उपयोग पर विचार करें। (फिर भी सरल if पर्याप्त होना चाहिए)

+0

if' यह स्पष्ट है कि वह केवल सूची पुनरावृति करना चाहता है नहीं है के करीब है, इस जवाब को हल करती है की "कुछ कर केवल एक ही उपयोग के मामले "एक सूची के साथ। –

-1

सबसे पहले मैं @ mlatu का जवाब है, जो else हालत


public inline fun Map.forEachElse(operation: (Map.Entry) -> Unit, elseBlock:() -> Unit): Unit { 
     if (!empty) 
      for (element in this) operation(element) 
     else 
      elseBlock() 
    } 

संभालती है लेकिन उपयोग बहुत सुंदर नहीं है के अलावा विस्तार समारोह बनाने के लिए सलाह देने के लिए करना चाहता था।

वास्तव में आप एक के लिए देख रहे हो सकता है कि इकाई

1

अन्य उत्तर के अलावा, आप भी सुरक्षित-कॉल ऑपरेटर संयोजन में विस्तार विधि isNotEmpty() साथ उपयोग कर सकते हैं। सुरक्षित कॉल के कारण, वापसी मूल्य वास्तव में Boolean? है जो या तो true, false या null हो सकता है।

when { 
    activities?.isNotEmpty() == true -> doSomething 
    else -> doSomethingElse 
} 

वैकल्पिक वाक्य रचना एल्विस ऑपरेटर का उपयोग: एक if या when खंड में अभिव्यक्ति का उपयोग करने के लिए आपको explictly जाँच करने के लिए अगर यह true होना चाहिए

when { 
    activities?.isNotEmpty() ?: false -> doSomething 
    else -> doSomethingElse 
} 
4

इस कोशिश करो! बहुत साफ़।

var array: List<String>? = null 
if (array.orEmpty().isEmpty()) { 
    // empty 
} else { 
    // not empty 
} 
+0

वास्तव में बहुत ही सुरुचिपूर्ण! –