2017-10-21 99 views
1

C'est ce que j'ai et ce que je veux atteindre:Pourquoi .map sur un mutableList ne change pas réellement les valeurs dans List dans Kotlin?

  1. J'ai une classe qui a un mutableList comme un champ.

  2. Je souhaite trouver un élément spécifique dans cette liste et le modifier.

C'est ce que je l'ai essayé jusqu'à présent:

  1. Ceci est la déclaration fonctionnelle j'espérais aurait travaillé, après que je l'ai aussi mis dans une fonction d'extension:

    fun Classroom.setNewParameters(id: String, modifiedName: String) { 
        this.students.filter { l -> l.id == id } 
           .map { l -> l.name = modifiedName } 
           .toList() 
    } 
    

    Mais la liste students semble être inchangée après l'appel de cette fonction.

  2. J'ai trouvé une solution « laid » avec le code ci-dessous:

    fun Classroom.setNewParameters(id: String, modifiedName: String) { 
        for (l : Student in this.students) { 
         if (l.id == id) { 
          l.name = modifiedName 
          break 
         } 
        } 
    } 
    

encore THO, je voudrais vraiment savoir pourquoi le premier bloc de code se comporte comme il le fait et n » Je n'ai aucun effet sur la liste.

+0

Je ne peux pas reproduire (mais vous abusez sérieusement de map(): il n'y a aucune raison de créer une nouvelle liste juste pour muter un des éléments de la liste originale). https://gist.github.com/jnizet/a25b87ff33ca156f446adbc8d6548bac. Publiez un programme minimal complet reproduisant votre problème. –

+0

@JBNizet ouais tu as raison ce n'était pas du tout cool. Je ne sais pas pourquoi je suis coincé avec le .map (le cas réel est un peu plus complexe mais n'a toujours pas de sens pour utiliser .map). J'ai posté une bonne réponse ci-dessous mais il l'a effacée, de toute façon il m'a juste dit d'aller avec 'students.forEach ({if (it.id == id) it.name = modifiedName})' et ça semble marcher très bien ! Pensez-vous que c'est une bonne solution aussi? –

+5

Non. Je pense que vous devriez plutôt utiliser 'list.find {it.id == id} ?. name = modifiedName'. C'est ce qui correspond à votre deuxième extrait: trouvez l'élément * first * avec l'identifiant donné, et changez son nom. –

Répondre

0

Vous pouvez penser à map comme un moyen de transformer l'entrée pour obtenir une nouvelle sortie. Normalement, il ne devrait pas muter état à l'intérieur, en d'autres termes, il doit être une fonction sans effets secondaires pour poursuivre maintenabilité

Dans votre cas, vous voulez clairement muter des éléments, pour que vous pouvez utiliser cet extrait de code:

fun Classroom.setNewParameters(id: String, modifiedName: String) { 
    this.students.filter { l -> l.id == id } 
       .onEach { l -> l.name = modifiedName } 
} 

En outre, même vous avez utilisé de manière incorrecte map devrait doit champ l.name modifier (sauf si vous avez mis en œuvre que vous possédez ou délégués getter/setter). Essayez de déboguer le point d'arrêt défini sur et de voir s'il reste des éléments après le filtrage

0

Noob ici mais j'ai juste vu quelque chose lié à ceci l'autre jour.

Y a-t-il une raison pour laquelle vous ne vérifieriez pas simplement si votre tableau contient l'ancienne valeur, retourner l'identifiant de l'élément et ensuite assigner votre nouvelle valeur à cet identifiant? Je suppose que je suis juste en train de souligner que cela pourrait être accompli avec une recherche de type "valeur dans le tableau" ... mais je suis encore trop nouveau pour connaître les avantages et les inconvénients de l'utiliser par rapport à la carte.

Un peu comme ceci ci-dessous, que je suis arrivé de Kotlin - Idiomatic way to check array contains value


"valeur" dans le tableau

Ce qui se traduit par l'API Java:

tableau

.contient (« valeur »)


donc je vérifier pour l'ancienne valeur du tableau, l'indice de rendement et de réaffecter cet indice avec la nouvelle valeur.