Foxtrot 1-5
Foxtrot 1-5

Reputation: 379

Android Kotlin Map Multiple Array into a list of object

So in this case I have three array that I want to map into a list of object (The objects has three parameters as well).

I have three arrays allProductCodeList, allProductNameList, and allProductQtyList (Content of this array is from a Retrofit Client response)

 allProductCodeList = response.body()?.data?.map { it?.stkProdcode }!!
 allProductNameList = response.body()?.data?.map { it?.proName }!!
 allProductQtyList = response.body()?.data?.map { it?.stkAllqty }!!

This is the content of the array I printed into the LogCat:

[![enter image description here][2]][2]

This is the Data class which I want to parse these arrays into:

data class ProcodeRecommendationListDataClass(
    val procode: String?,
    val productName: String?,
    val qty: Int?
)

What I want to do is parse these three array into a list that will looks like:

[ProcodeRecommendationListDataClass("0100009","", 2),ProcodeRecommendationListDataClass("0100061","", 1),ProcodeRecommendationListDataClasslass("0100062","", 6)]

I've done it when I only have two arrays to map (I use this solution for it). But now it I have three arrays, I confused.

If there's any detail I miss to point out, Just let me know !

Upvotes: 0

Views: 2613

Answers (4)

Fred
Fred

Reputation: 17095

One forward straight way is to use one more zip - someone once said all problems are solved with one more level of inderection:

allProductCodeList
    .zip(allProductNameList)
    .zip(allProductQtyList)
    .map { (codeAndName, qt) ->
        ProcodeRecommendationListDataClass(
            codeAndName.first,
            codeAndName.second,
            qt
        )
    }

It doesn't look super pretty, but it should be ok.


Another way is to create your own zip that takes 2 lists:

fun <X, Y, Z, R> List<X>.zipWith(l1: List<Y>, l2: List<Z>, transform: (X, Y, Z) -> R): List<R> {
  val length = min(min(size, l1.size), l2.size)

  val result = mutableListOf<R>()
  for (i in 0 until length) {
    result.add(transform(get(i), l1[i], l2[i]))
  }

  return result
}

fun main() {
  val k = allProductCodeList.zipWith(allProductNameList, allProductQtyList) { code, name, qt ->
        ProcodeRecommendationListDataClass(
            code,
            name,
            qt
        )
    }

  println(k)
}

Basically extends a list of X that takes 2 other lists. It iterates through them applying the transform method (this is so you can map the elements as you go).

This will iterate always the smallest amount of elements - in other words, you won't get more elements than the smallest list. I can't be sure, but I assume the default implementation does something similar.

Upvotes: 3

Abhay Koradiya
Abhay Koradiya

Reputation: 2117

You can use mapIndexed instead of map. use index to get third data.

val list = allProductCodeList.zip(allProductNameList)
        .mapIndexed { index, pair -> SomeClass(pair.first, pair.second,allProductQtyList[index]) }

Upvotes: 0

Deepak Ror
Deepak Ror

Reputation: 2254

1. This is you three arrays

allProductCodeList = response.body()?.data?.map { it?.stkProdcode }!!
 allProductNameList = response.body()?.data?.map { it?.proName }!!
 allProductQtyList = response.body()?.data?.map { it?.stkAllqty }!!

2. Make A New List

List<ProcodeRecommendationListDataClass> finalList = List()

3. Run a for loop with any of three array size with indices;

 for(pos in allProductCodeList.indices){

finalList.add(ProcodeRecommendationListDataClass(allProductCodeList[pos],
allProductNameList[pos],
allProductQtyList[pos] ))

}

Now finalList is your result.

Upvotes: 3

IR42
IR42

Reputation: 9732

Why not just create objects in place?

val allProducts = response.body()?.data?.map { 
    ProcodeRecommendationListDataClass(it?.stkProdcode, it?.proName, it?.stkAllqty) 
} ?: emptyList()

Upvotes: 1

Related Questions