วิธีแปลง List เป็น Map ใน Kotlin


169

ตัวอย่างเช่นฉันมีรายการสตริงเช่น:

val list = listOf("a", "b", "c", "d")

และฉันต้องการแปลงเป็นแผนที่โดยที่สตริงเป็นกุญแจ

ฉันรู้ว่าฉันควรใช้.toMap()ฟังก์ชั่นนี้ แต่ฉันไม่รู้ว่าทำอย่างไรและฉันไม่ได้เห็นตัวอย่างของมัน

คำตอบ:


317

คุณมีสองทางเลือก:

คนแรกและคนที่มีประสิทธิภาพมากที่สุดคือการใช้associateByฟังก์ชั่นที่ใช้ lambdas สองตัวเพื่อสร้างคีย์และค่าและอินไลน์การสร้างแผนที่:

val map = friends.associateBy({it.facebookId}, {it.points})

ที่สองน้อยกว่า performant คือการใช้mapฟังก์ชั่นมาตรฐานเพื่อสร้างรายการPairซึ่งสามารถใช้โดยtoMapการสร้างแผนที่สุดท้าย:

val map = friends.map { it.facebookId to it.points }.toMap()

1
ขอบคุณ. มันเร็วกว่าเพราะสร้างแผนที่และไม่แปลงรายการคู่เป็นแผนที่เช่นในตัวอย่างของฉัน
LordScone

4
@lordScone แน่นอนการจัดสรร Pairอินสแตนซ์อาจมีค่าใช้จ่ายสูงมากสำหรับคอลเลกชันขนาดใหญ่
voddan

41

จากListถึงMapด้วยassociateฟังก์ชั่น

ด้วย Kotlin 1.3 มีฟังก์ชั่นที่เรียกว่าList มีการประกาศดังต่อไปนี้:associateassociate

fun <T, K, V> Iterable<T>.associate(transform: (T) -> Pair<K, V>): Map<K, V>

ส่งคืนMapคู่คีย์ - ค่าที่มีให้โดยtransformฟังก์ชั่นที่ใช้กับองค์ประกอบของคอลเลกชันที่กำหนด

การใช้งาน:

class Person(val name: String, val id: Int)

fun main() {
    val friends = listOf(Person("Sue Helen", 1), Person("JR", 2), Person("Pamela", 3))
    val map = friends.associate({ Pair(it.id, it.name) })
    //val map = friends.associate({ it.id to it.name }) // also works

    println(map) // prints: {1=Sue Helen, 2=JR, 3=Pamela}
}    

จากListถึงMapด้วยassociateByฟังก์ชั่น

ด้วย Kotlin, มีฟังก์ชั่นที่เรียกว่าList มีการประกาศดังต่อไปนี้:associateByassociateBy

fun <T, K, V> Iterable<T>.associateBy(keySelector: (T) -> K, valueTransform: (T) -> V): Map<K, V>

ส่งคืนMapค่าที่มีโดยvalueTransformและจัดทำดัชนีโดยkeySelectorฟังก์ชั่นที่ใช้กับองค์ประกอบของคอลเลกชันที่กำหนด

การใช้งาน:

class Person(val name: String, val id: Int)

fun main() {
    val friends = listOf(Person("Sue Helen", 1), Person("JR", 2), Person("Pamela", 3))
    val map = friends.associateBy(keySelector = { person -> person.id }, valueTransform = { person -> person.name })
    //val map = friends.associateBy({ it.id }, { it.name }) // also works

    println(map) // prints: {1=Sue Helen, 2=JR, 3=Pamela}
}

3
ความแตกต่างระหว่างภาคีและ AssociBy คืออะไร? ฉันต้องการที่จะใช้อย่างใดอย่างหนึ่งมากกว่าที่อื่นเห็นว่าพวกเขาให้ผลลัพธ์เดียวกัน
waynesford

11
  • แปลงองค์ประกอบลำดับ Iteratable เป็นแผนที่ใน kotlin
  • ภาคีกับภาคีโดยภาคีกับ:

* อ้างอิง: เอกสารประกอบ Kotlin

1- เชื่อมโยง (เพื่อตั้งค่าคีย์และค่า): สร้างแผนที่ที่สามารถตั้งค่าองค์ประกอบคีย์และค่า:

IterableSequenceElements.associate { newKey to newValue } //Output => Map {newKey : newValue ,...}

หากคู่ใดคู่หนึ่งมีรหัสเดียวกันคีย์สุดท้ายจะถูกเพิ่มลงในแผนที่

แผนที่ที่ส่งคืนจะรักษาลำดับการวนซ้ำของอาร์เรย์ดั้งเดิม

2- AssociBy (เพียงตั้งค่าคีย์ตามการคำนวณ): สร้างแผนที่ที่เราสามารถตั้งค่าคีย์ใหม่องค์ประกอบแบบอะนาล็อกจะถูกตั้งค่า

IterableSequenceElements.associateBy { newKey } //Result: => Map {newKey : 'Values will be set  from analogous IterableSequenceElements' ,...}

3- AssociWith (เพิ่งตั้งค่าโดยการคำนวณ): สร้างแผนที่ที่เราสามารถตั้งค่าใหม่องค์ประกอบแบบอะนาล็อกจะถูกตั้งค่าสำหรับคีย์

IterableSequenceElements.associateWith { newValue }  //Result => Map { 'Keys will be set from analogous IterableSequenceElements' : newValue , ...}

ตัวอย่างจากเคล็ดลับ Kotlin: ป้อนคำอธิบายรูปภาพที่นี่


10

คุณสามารถใช้associateสำหรับงานนี้:

val list = listOf("a", "b", "c", "d")
val m: Map<String, Int> = list.associate { it to it.length }

ในตัวอย่างนี้สตริงจากการlistเป็นกุญแจและความยาวที่สอดคล้องกัน (เป็นตัวอย่าง) กลายเป็นค่าภายในแผนที่


7

หากคุณมีรายการที่ซ้ำกันgroupByในรายการของคุณที่คุณไม่ต้องการที่จะสูญเสียคุณสามารถทำเช่นนี้โดยใช้

มิฉะนั้นอย่างที่ทุกคนบอกว่าใช้associate/By/With(ซึ่งในกรณีของการทำซ้ำฉันเชื่อว่าจะคืนค่าสุดท้ายด้วยคีย์นั้นเท่านั้น)

ตัวอย่างการจัดกลุ่มรายชื่อบุคคลตามอายุ:

class Person(val name: String, val age: Int)

fun main() {
    val people = listOf(Person("Sue Helen", 31), Person("JR", 25), Person("Pamela", 31))

    val duplicatesKept = people.groupBy { it.age }
    val duplicatesLost = people.associateBy({ it.age }, { it })

    println(duplicatesKept)
    println(duplicatesLost)
}

ผล:

{31=[Person@41629346, Person@4eec7777], 25=[Person@3b07d329]}
{31=Person@4eec7777, 25=Person@3b07d329}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.