কোটলিনে একাধিক মানের উপর ভিত্তি করে / তুলনা করতে কিভাবে?


85

বলুন আমার একটি আছে class Foo(val a: String, val b: Int, val c: Date)এবং আমি Fooতিনটি বৈশিষ্ট্যের উপর ভিত্তি করে এর একটি তালিকা বাছাই করতে চাই । আমি এই সম্পর্কে কিভাবে যেতে হবে?

উত্তর:


149

কোটলিনের stdlib এর জন্য বেশ কয়েকটি সহায়ক সহায়ক পদ্ধতি সরবরাহ করে।

প্রথমে, আপনি 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()

বাছাইয়ের দিকনির্দেশ

আপনার যদি কিছু মানকে আরোহণ এবং অন্য মানগুলিতে আরোহণের প্রয়োজন হয় তবে স্ট্ডলিব তার জন্য ফাংশনও সরবরাহ করে:

list.sortedWith(compareBy<Foo> { it.a }.thenByDescending { it.b }.thenBy { it.c })

পারফরম্যান্স বিবেচনা

varargসংস্করণ compareValuesByবাইটকোড বেনামী শ্রেণীর অর্থ মধ্যে inlined নয় lambdas জন্য তৈরি করা হবে। তবে, যদি ল্যাম্বডাসরা নিজেরাই রাষ্ট্র গ্রহণ না করে তবে প্রতিবার ল্যাম্বডাস ইনস্ট্যান্ট করার পরিবর্তে সিঙ্গেলটন উদাহরণ ব্যবহার করা হবে।

মন্তব্যগুলিতে পল ওউইটাসেকেক যেমন উল্লেখ করেছেন , একাধিক নির্বাচকদের সাথে তুলনা করা প্রতিবার ভার্গ কলের জন্য একটি অ্যারে ইনস্ট্যান্ট করবে। অ্যারেটি বের করে আপনি এটি অনুকূলিত করতে পারবেন না কারণ এটি প্রতিটি কলে অনুলিপি করা হবে। অন্যদিকে আপনি যা করতে পারেন তা হ'ল যুক্তিটিকে স্থির তুলনাকারী উদাহরণে এক্সট্রাক্ট করে আবার ব্যবহার করুন:

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)
    }
}

4
মনে রাখবেন যে আপনি যদি একাধিক ল্যাম্বডাস ফাংশন ব্যবহার করেন (ঠিক তেমন একটি ওভারলোড রয়েছে যা ইনলাইনগুলি থাকে) তবে সেগুলি ইনলাইন করা হবে না । যার অর্থ ComapreTo এর প্রতিটি কল একটি নতুন অবজেক্ট তৈরি করে। আপনি বাছাইকারীদের সঙ্গী অবজেক্টে সরাতে পারেন তা রোধ করতে যাতে নির্বাচকদের কেবল একবার বরাদ্দ দেওয়া হয়। আমি এখানে একটি স্নিপড
পল ওউইটেসেক

4
@ কিরিলরখমান এটি ফাংশনগুলির জন্য একক তৈরি করে কিন্তু এখনও অ্যারে বরাদ্দ করে:ANEWARRAY kotlin/jvm/functions/Function1
পল ওউইটেসেক

4
compareByএকাধিক ল্যাম্বডাস সহ কোটলিন 1.1.3 দিয়ে শুরু করে প্রতিটি compareToকলটিতে নতুন অ্যারে বরাদ্দ করা হবে না ।
ইলিয়া

4
@ ইলিয়া আপনি কি আমাকে এই জাতীয় অপ্টিমাইজেশনের জন্য প্রাসঙ্গিক চেঞ্জলগ বা অন্যান্য তথ্যের দিকে নির্দেশ করতে পারেন?
কিরিল রাখমান


0

যদি আপনি উত্থানের ক্রমটিকে বাছাই করতে চান তবে আপনি গৃহীত উত্তরটি ব্যবহার করতে পারেন:

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 }))


0

আপনার যদি একাধিক ক্ষেত্র অনুসারে বাছাই করতে হয় এবং কিছু ক্ষেত্র অবতরণ করে এবং অন্যগুলি আরোহণ করে আপনি ব্যবহার করতে পারেন:

YOUR_MUTABLE_LIST.sortedWith(compareBy<YOUR_OBJECT> { it.PARAM_1}.thenByDescending { it.PARAM_2}.thenBy { it.PARAM_3})

4
এটি আমার উত্তরে isাকা পড়েছে।
কিরিল রাখমান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.