【问题标题】:Kotlin: Merge two different list into one with selected data from both listsKotlin:将两个不同的列表合并为一个,并从两个列表中选择数据
【发布时间】:2018-12-05 13:26:30
【问题描述】:

我想合并两个不同类型的列表并创建另一个列表,其中包含两个列表中的数据。此外,只有在标识符匹配时才应该合并(例如两个列表中的 id 匹配)

Employee(val employeeId: Int,
         val employeeName: String,
         val address: String)

LaptopInfo(val laptopId: Int,
         val employeeId: String,
         val team: String)

EmployeeLaptopInfo(val laptopId: Int,
         val employeeId: String,
         val employeeName: String,
         val address: String)

所以有EmployeeLaptopInfo 的列表,我想仅当两个列表中的employeeId 匹配时才将EmployeeLaptopInfo 添加到List<EmployeeLaptopInfo>

val employeeLaptopInfoList = mutableListOf<EmployeeLaptopInfo>()
val employeeIds = employeeList.map { it.employeeId }.toSet()

lapTopInfoList.filter { employeeIds.contains(it.employeeId) }
   .map {
      val employeeLaptopInfo = EmployeeLaptopInfo(it.laptopId, laptopId.employeeId, "can't get info", "can't get info")
      employeeLaptopInfoList.add(employeeLaptopInfo)
   }

但是这样我就不会从两个列表中获取详细信息。有什么方法可以不使用 for 循环且高效地做到这一点。

【问题讨论】:

标签: android arraylist kotlin merge


【解决方案1】:

我已经优化了 Yoni Gibbs 的 解决方案。这个想法是filteremployeeId 存在于Employee 中的笔记本电脑。然后将每个laptop 转换为EmployeeLaptopInfo

data class Employee(val employeeId: Int, val employeeName: String, val address: String)

data class LaptopInfo(val laptopId: Int, val employeeId: Int, val team: String)

data class EmployeeLaptopInfo(val laptopId: Int, val employeeId: Int, val employeeName: String, val address: String)

fun main(args: Array<String>) {
    val employees = listOf<Employee>()
    val laptops = listOf<LaptopInfo>()

    val employeesById: Map<Int, Employee> = employees.associateBy { it.employeeId }

    val result = laptops.filter { employeesById[it.employeeId] != null }.map { laptop ->
        employeesById[laptop.employeeId]?.let { employee ->
            EmployeeLaptopInfo(laptop.laptopId, laptop.employeeId, employee.employeeName, employee.address)
        }
    }
}

【讨论】:

    【解决方案2】:

    我认为您的类在某些属性的数据类型中存在错误,所以我将它们更改为:

    class Employee(val employeeId: Int, val employeeName: String, val address: String)
    class LaptopInfo(val laptopId: Int, val employeeId: Int, val team: String)
    class EmployeeLaptopInfo(val laptopId: Int, val employeeId: Int, val employeeName: String, val address: String)
    

    如果这些是初始列表:

    val employeeList = mutableListOf<Employee>()
    val laptopInfoList = mutableListOf<LaptopInfo>()
    

    然后您通过在两个列表中查找employeeId 的对应值来映射employeeList

    val employeeLaptopInfoList =
            employeeList.mapNotNull { emp ->
                val laptop = laptopInfoList.find { it.employeeId == emp.employeeId }
                if (laptop == null) null 
                else EmployeeLaptopInfo(
                    laptop.laptopId,
                    emp.employeeId,
                    emp.employeeName,
                    emp.address)
            }
    

    【讨论】:

      【解决方案3】:

      我认为最好先创建两张地图,一张用于笔记本电脑,一张用于员工,两者都键入employeeId。然后您可以执行以下操作:

          val employees = listOf<Employee>()
          val laptops = listOf<LaptopInfo>()
      
          val laptopsByEmployeeId: Map<Int, List<LaptopInfo>> = laptops.groupBy { it.employeeId }
          val employeesById: Map<Int, Employee> = employees.associateBy { it.employeeId }
          val result = laptopsByEmployeeId.flatMap { (employeeId, laptops) ->
              laptops.mapNotNull { laptop ->
                  employeesById[employeeId]?.let { employee ->
                      EmployeeLaptopInfo(laptop.laptopId, employeeId, employee.employeeName, employee.address)
                  }
              }
          }
      

      这意味着您永远不会在一个循环内循环另一个列表,这可能是低效的。相反,您使用地图通过 ID 快速获取项目。

      (另外,根据 forpas 的回答,我假设 employeeId 的数据类型在所有类中都应该相同,例如 Int。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-27
        • 2014-01-03
        • 2014-04-01
        • 2015-04-01
        • 2011-09-12
        • 2019-09-08
        相关资源
        最近更新 更多