31 votes

Obtenir des éléments peu courants à partir de deux listes - KOTLIN

J'ai deux listes de la même classe modèle (STUDENT), un exemple de structure d'objet étudiant est donné ci-dessous,

{
    "_id": "5a66d78690429a1d897a91ed",
        "division": "G",
        "standard": "X",
        "section": "Secondary",
        "lastName": "Sawant",
        "middleName": "Sandeep",
        "firstName": "Shraddha",
        "pin": 12345,
        "isEditable": true,
        "isTracked": false
}

Une liste contient 3 objets et une autre 2. Disons que la liste A contient 1, 2, 3 étudiants et que la liste B contient 1, 2, 3 étudiants.

Ma question est donc la suivante : existe-t-il des fonctions intégrées pour obtenir l'élément non commun ? en comparant seulement l'identifiant ? Sinon, comment puis-je résoudre ce problème ?

Pour votre information, voici les deux approches que j'ai utilisées pour résoudre le problème, mais j'ai échoué lamentablement.

Approche 1.

internal fun getDistinctStudents(studentsList: List<Students>, prefStudents: List<Students>): List<Students> {
    val consolidated = prefStudents.filter {
        prefStudents.any { students: Students -> it._id == students._id }
    }
    return prefStudents.minus(consolidated)
}

Approche 2.

internal fun getDistinctStudents(studentsList: List<Students>, prefStudents: List<Students>): List<Students> {
    val consolidatedStudents = studentsList + prefStudents
    val distinctStudents = consolidatedStudents.distinctBy{ it._id }
    return prefStudents.minus(distinctStudents)
}

Toute forme d'aide sera grandement appréciée.

Merci

2 votes

Consolidez les deux listes et créez une carte de hachage (hashmap) de la chaîne à l'entier qui est l'identifiant de l'étudiant au nombre d'occurrences, puis bouclez sur la carte de hachage et récupérez les clés qui n'ont qu'une seule occurrence.

0 votes

Vous pouvez créer une correspondance entre l'étudiant et le nombre d'occurrences afin d'obtenir la liste des étudiants à la fin.

46voto

Mikezx6r Points 6541

Une façon plus Kotlin de réaliser ce que Ahmed Hegazy a posté. La carte contiendra une liste d'éléments, plutôt qu'une clé et un nombre.

Utilisation de HashMap et des modules intégrés de Kotlin. groupBy crée une Map avec une clé telle que définie dans la Lambda (id dans ce cas), et une Liste des éléments (List pour ce scénario)

Puis en filtrant les entrées dont la taille de la liste est différente de 1.

Et enfin, la convertir en une seule liste d'étudiants (d'où l'appel à flatMap)

val list1 = listOf(Student("1", "name1"), Student("2", "name2"))
val list2 = listOf(Student("1", "name1"), Student("2", "name2"), Student("3", "name2"))

val sum = list1 + list2
return sum.groupBy { it.id }
    .filter { it.value.size == 1 }
    .flatMap { it.value }

2 votes

Belle solution ! :)

0 votes

En fait Oui, c'est une bonne solution,

0 votes

KIS. Rester simple. J'ai adoré.

32voto

Jonathan Kibet Points 47

Je sais que c'est un vieux post mais je crois qu'il existe une solution plus propre et plus courte. Voir l'exemple ci-dessous en utilisant Mikezx6r dont la réponse a été acceptée ci-dessus.

val list1 = listOf(Student("1", "name1"), Student("2", "name2"))
val list2 = listOf(Student("1", "name1"), Student("2", "name2"), Student("3", "name2"))

val difference = list2.toSet().minus(list1.toSet())

8 votes

Cela ne fonctionne que si vous voulez des éléments de la liste 2 qui ne se trouvent pas dans la liste 1. Ce n'est pas un résultat d'"éléments distincts" de 2 listes. list1.toSet().minus(list2.toSet()) ne donne aucun élément, donc soyez prudent en utilisant cette réponse.

3voto

zsmb13 Points 36441

En attendant que quelqu'un trouve une solution plus claire et plus courte, en voici une qui fonctionne et qui me semble assez facile à lire :

internal fun getDistinctStudents(studentsList: List<Students>, prefStudents: List<Students>): List<Students> {
    val studentsIds = studentsList.map { it._id }          // [ 1, 2, 3 ]
    val prefStudentIds = prefStudents.map { it._id }       // [ 1, 2 ]
    val commonIds = studentsIds.intersect(prefStudentIds)  // [ 1, 2 ]

    val allStudents = studentsList + prefStudents      // [ Student1, Student2, Student3, Student1, Student2 ]
    return allStudents.filter { it._id !in commonIds } // [ Student3 ]
}

Si vous avez un très grand nombre d'étudiants (des centaines), envisagez d'utiliser des séquences pour les différentes étapes, et peut-être qu'un filtrage avant de concaténer les deux dernières listes pourrait également être utile :

val filteredStudents = studentsList.filter { it._id !in commonIds }
val filteredPrefStudents = prefStudents.filter { it._id !in commonIds }
return filteredStudents + filteredPrefStudents

Edit : voir cette réponse à la place .

0 votes

J'essaierai et je vous tiendrai au courant. Merci pour votre effort :)

2 votes

Quelqu'un a fini par poster une solution intéressante, voir aquí

0 votes

J'ai trouvé une solution Merci de vérifier si c'est la bonne façon de procéder ? Je vous serais très reconnaissant de vérifier la solution et de m'indiquer si quelque chose ne va pas.

3voto

Hegazy Points 106

Voici la solution en utilisant un HashMap, le code pourrait être meilleur, mais je suis très novice en kotlin

fun getDistinctStudents(studentsList: List<Student>, prefStudents: List<Student>): List<Student> {
    val studentsOccurrences = HashMap<Student, Int>()
    val consolidatedStudents = studentsList + prefStudents
    for (student in consolidatedStudents) {
        val numberOfOccurrences = studentsOccurrences[student]
        studentsOccurrences.put(student, if(numberOfOccurrences == null) 1 else numberOfOccurrences + 1)
    }
    return consolidatedStudents.filter { student -> studentsOccurrences[student] == 1 }
}

Votre classe d'étudiant devrait être une classe de données ou au moins remplacer hashcode et equals pour être utilisé comme clé.

0 votes

J'essaierai et je vous tiendrai au courant. Merci pour votre effort :)

1voto

Sanoop Points 2483

Enfin, après quelques recherches dans la documentation de Kotlin, j'ai trouvé la solution. La fonction que je recherchais était la suivante filterNot

Voici la solution complète que j'ai essayée.

internal fun getDistinctStudents(studentsList: List<Students>, prefStudents: List<Students>): List<Students> {
    return prefStudents.filterNot { prefStudent ->
         studentsList.any {
             prefStudent._id == it._id
         }
    } 
}

Ce qui a retourné les éléments peu communs.

1 votes

Vous n'obtiendrez pas les étudiants qui sont seulement en studentsList Seuls ceux qui se trouvent uniquement dans les prefStudents . Je pense que vous devriez vous en tenir à la solution de @Mikezx6r.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X