कहो कि मेरे पास एक है class Foo(val a: String, val b: Int, val c: Date)
और मैं Foo
तीनों गुणों के आधार पर सूची बनाना चाहता हूं । मैं इसे किस तरह लूं?
कहो कि मेरे पास एक है class Foo(val a: String, val b: Int, val c: Date)
और मैं Foo
तीनों गुणों के आधार पर सूची बनाना चाहता हूं । मैं इसे किस तरह लूं?
जवाबों:
कोटलिन की स्टडलिब इसके लिए कई उपयोगी सहायक विधियां प्रदान करती है।
सबसे पहले, आप compareBy()
विधि का उपयोग कर एक तुलनित्र को परिभाषित कर सकते हैं और sortedWith()
सूची की एक हल की गई प्रतिलिपि प्राप्त करने के लिए इसे विस्तार विधि में पास कर सकते हैं :
val list: List<Foo> = ...
val sortedList = list.sortedWith(compareBy({ it.a }, { it.b }, { it.c }))
दूसरा, आप सहायक विधि का उपयोग करके इसे Foo
लागू Comparable<Foo>
कर सकते हैं compareValuesBy()
:
class Foo(val a: String, val b: Int, val c: Date) : Comparable<Foo> {
override fun compareTo(other: Foo)
= compareValuesBy(this, other, { it.a }, { it.b }, { it.c })
}
फिर आप sorted()
सूची की क्रमबद्ध प्रतिलिपि प्राप्त करने के लिए बिना पैरामीटर के विस्तार विधि को कॉल कर सकते हैं :
val sortedList = list.sorted()
यदि आपको कुछ मूल्यों पर आरोही और अन्य मूल्यों पर उतरने की जरूरत है, तो stdlib उसके लिए भी कार्य करता है:
list.sortedWith(compareBy<Foo> { it.a }.thenByDescending { it.b }.thenBy { it.c })
का vararg
संस्करण compareValuesBy
बाईटकोड में इनबिल्ड नहीं है जिसका अर्थ है कि अनाम वर्ग लैम्बडा के लिए उत्पन्न होंगे। हालाँकि, यदि लंबोदर स्वयं राज्य पर कब्जा नहीं करते हैं, तो हर बार लैम्बदास को त्वरित करने के बजाय सिंगलटन इंस्टेंस का उपयोग किया जाएगा।
जैसा कि पॉल Woitaschek द्वारा टिप्पणी में कहा गया है , कई चयनकर्ताओं के साथ तुलना करने से वेरग कॉल के लिए हर बार एक सरणी तुरंत समाप्त हो जाएगी। आप इसे सरणी को निकालकर अनुकूलित नहीं कर सकते क्योंकि यह हर कॉल पर कॉपी किया जाएगा। दूसरी ओर आप क्या कर सकते हैं, तर्क को एक स्थिर तुलनित्र उदाहरण में निकालें और उसका पुन: उपयोग करें:
class Foo(val a: String, val b: Int, val c: Date) : Comparable<Foo> {
override fun compareTo(other: Foo) = comparator.compare(this, other)
companion object {
// using the method reference syntax as an alternative to lambdas
val comparator = compareBy(Foo::a, Foo::b, Foo::c)
}
}
ANEWARRAY kotlin/jvm/functions/Function1
compareBy
कई लैंबडों के साथ कोटलिन 1.1.3 के साथ शुरू हर compareTo
कॉल पर नए सरणी आवंटित नहीं करेगा ।
यदि आप अवरोही क्रम में क्रमबद्ध करना चाहते हैं, तो आप स्वीकृत उत्तर का उपयोग कर सकते हैं:
list.sortedWith(compareByDescending<Foo> { it.a }.thenByDescending { it.b }.thenByDescending { it.c })
या एक्सटेंशन फ़ंक्शन बनाएं जैसे compareBy
:
/**
* Similar to
* public fun <T> compareBy(vararg selectors: (T) -> Comparable<*>?): Comparator<T>
*
* but in descending order.
*/
public fun <T> compareByDescending(vararg selectors: (T) -> Comparable<*>?): Comparator<T> {
require(selectors.size > 0)
return Comparator { b, a -> compareValuesByImpl(a, b, selectors) }
}
private fun <T> compareValuesByImpl(a: T, b: T, selectors: Array<out (T) -> Comparable<*>?>): Int {
for (fn in selectors) {
val v1 = fn(a)
val v2 = fn(b)
val diff = compareValues(v1, v2)
if (diff != 0) return diff
}
return 0
}
और का उपयोग करें: list.sortedWith(compareByDescending ({ it.a }, { it.b }, { it.c }))
।
यदि आपको कई क्षेत्रों के द्वारा सॉर्ट करने की आवश्यकता है, और कुछ क्षेत्र अवरोही और अन्य आरोही द्वारा जो आप उपयोग कर सकते हैं:
YOUR_MUTABLE_LIST.sortedWith(compareBy<YOUR_OBJECT> { it.PARAM_1}.thenByDescending { it.PARAM_2}.thenBy { it.PARAM_3})