kotlin how to remove duplicate through some value in object array? - kotlin

how to remove duplicate through some value in object array?
data class Person(
val id: Int,
val name: String,
val gender: String
)
val person1 = Person(1, "Lonnie", "female")
val person2 = Person(2, "Noah", "male")
val person3 = Person(3, "Ollie", "female")
val person4 = Person(4, "William", "male")
val person5 = Person(5, "Lucas", "male")
val person6 = Person(6, "Mia", "male")
val person7 = Person(7, "Ollie", "female")
val personList = listOf(person1,person2,person3,person4,person5,person6,person7)
Person 3 and person 7 have a "female" gender and have the same name. So person7 needs to be removed.
But "male" gender can have duplicated name.
And the order of the list must be maintained.
expect result
[
Person(1, "Lonnie", "female"),
Person(2, "Noah", "male"),
Person(3, "Ollie", "female"),
Person(4, "William", "male"),
Person(5, "Lucas", "male"),
Person(6, "Mia", "male"),
]

You could do something like this, assuming the order is indicated by the id field of the Person class:
val personList = listOf(person1,person2,person3,person4,person5,person6,person7)
.partition { it.name == "male" }
.let { (males, females) -> males + females.distinctBy { it.name } }
.sortedBy { it.id }

I believe this does what you want:
val result = personList.filter {
person -> person.gender == "male" || (personList.first {
person.name == it.name && person.gender == it.gender
} == person)
}

Related

kotlin exposed select with foreign key

I have two tables like as I described below
object Categories : LongIdTable() {
val name = varchar(name = "name", length = 50).uniqueIndex()
val count = integer(name = "count")
val page = integer(name = "page")
}
object Images : LongIdTable() {
val color = varchar(name = "color", length = 100)
val blurHash = varchar(name = "blurHash", length = 200)
val unsplashId = varchar(name = "unsplashId", length = 200)
val category = reference(name = "category", Categories.name).nullable()
val isAvailable = bool(name = "isAvailable")
val imagePath = varchar(name = "imagePath", length = 500)
}
and here is my Image & Category data classes
#Serializable
data class Image(
val id: Long,
val unsplashId: String,
val isAvailable: Boolean = false,
val color: String,
val blurHash: String,
var category: Category?,
val imagePath: String,
)
#Serializable
data class Category(
val id: Long,
val name: String,
val count: Int,
var imagePath: String?,
val page: Int
)
when I want to find images by their id I can't map category attribute
fun getImageById(id: Long): Image {
val images = ArrayList<Image>()
var categoryName = ""
transaction {
Images.select {
Images.id eq id
}.map { row ->
categoryName = row[Images.category]!!
images.add(
Image(
id = row[Images.id].value,
unsplashId = row[Images.unsplashId],
isAvailable = false,
color = row[Images.color],
blurHash = row[Images.blurHash],
category = null,
imagePath = row[Images.imagePath]
)
)
}
images[0].category = categoryRepository.getCategoryByName(categoryName)
}
return images[0]
}
how can I solve this priblem?

Kotlin flatten + map of nested objects

I have a list of objects that looks like:
data class Classroom(
val id: Int,
val name: String,
val students: List<Student>
)
data class Student(
val id: Int,
val name: String,
val age: Int,
val gpa: Long,
)
I wanna have a hash map that maps Student.name -> Student of all the students that are in all of the classes (regardless of which student belongs to each class).
My input is a List of Classroom
How can i achieve that elegantly?
val studentMap: Map<String, Student> = classrooms
.flatMap { it.students }
.map { student -> student.name to student }
.toMap()
Use flatMap to extract all the students
map them to name/student pairs
Convert to a map
Here is the the setup and test code, that you should have provided in the question.
fun generateClassrooms() : List<Classroom> {
val classANames = listOf("foo", "bar", "baz")
val classBNames = listOf("baz", "asdf", "ghjk")
val classCNames = listOf("asdf", "ghjk", "bar", "qwerty")
val student = Student(0, "name", 0, 0)
val classAStudents = classANames.map { student.copy(name = it) }
val classBStudents = classBNames.map { student.copy(name = it) }
val classCStudents = classCNames.map { student.copy(name = it) }
val classroom = Classroom(0, "classroom", emptyList())
val classA = classroom.copy(students = classAStudents)
val classB = classroom.copy(students = classBStudents)
val classC = classroom.copy(students = classCStudents)
return listOf(classA, classB, classC)
}
fun main() {
val classrooms = generateClassrooms()
val studentMap: Map<String, Student> = classrooms
.flatMap { it.students }
.map { student -> student.name to student }
.toMap()
for (student in studentMap) println(student)
}
Running this produces:
foo=Student(id=0, name=foo, age=0, gpa=0)
bar=Student(id=0, name=bar, age=0, gpa=0)
baz=Student(id=0, name=baz, age=0, gpa=0)
asdf=Student(id=0, name=asdf, age=0, gpa=0)
ghjk=Student(id=0, name=ghjk, age=0, gpa=0)
qwerty=Student(id=0, name=qwerty, age=0, gpa=0)

contents of a list after filter

would you please let me how can I print out the contents of persons?
the output of the code is
[Person#72ea2f77, Person#33c7353a, Person#681a9515, Person#3af49f1c,
Person#19469ea2]
code:
fun main(args: Array<String>) {
val person1 = Person("xyz1", 10);
val person2 = Person("xyz2", 20);
val person3 = Person("xyz3", 30);
val person4 = Person("xyz4", 40);
val person5 = Person("xyz5", 50);
var persons = listOf(
person1, person2, person3, person4 , person5)
.asSequence()
.filter { x-> x.age >=30 }
println(persons.toList())
}
You can either implement toString() method in the Person class or you can make Person class a data class.
One easy way to show the contents of the Person class is to override the toString method in the Persons class. Here is a working example:
fun main(args: Array<String>) {
val person1 = Person("xyz1", 10);
val person2 = Person("xyz2", 20);
val person3 = Person("xyz3", 30);
val person4 = Person("xyz4", 40);
val person5 = Person("xyz5", 50);
var persons = listOf(
person1, person2, person3, person4, person5)
.asSequence()
.filter { x -> x.age >= 30 }
println(persons.toList())
}
class Person constructor(val name: String, val age: Int) {
override fun toString(): String {
return "$name is $age years old."
}
}
Will output:
[xyz3 is 30 years old., xyz4 is 40 years old., xyz5 is 50 years old.]

how to use distinct operator

would you please let me know the reason why I am getting the output mentioned below??
I expected to get the following out put:
[Person(_name=xyz4, _age=30),
Person(_name=xyz5, _age=50)]
because of distinct operator
Main:
fun main(args: Array<String>) {
val person1 = Person("xyz1", 10);
val person2 = Person("xyz2", 20);
val person3 = Person("xyz3", 30);
val person4 = Person("xyz4", 30);
val person5 = Person("xyz5", 50);
var persons = listOf(
person1, person2, person3, person4 , person5)
.asSequence()
.filter { x-> x.age >=30 }
.distinct()
println(persons.toList())
}
output:
[Person(_name=xyz3, _age=30), Person(_name=xyz4, _age=30),
Person(_name=xyz5, _age=50)]
you can use
.distinctBy { it.age }
instead of
.distinct()
if order of elements is important you can add sortedBy like this
fun main(args: Array<String>) {
val person1 = Person("xyz1", 10)
val person2 = Person("xyz2", 20)
val person3 = Person("xyz3", 30)
val person4 = Person("xyz4", 30)
val person5 = Person("xyz5", 50)
val persons = listOf(
person1, person2, person3, person4, person5)
.reversed()
.filter { x -> x.age >= 30 }
.distinctBy { it.age }
.sortedBy { it.age }
println(persons.toList())
}

How do I use "for" for this case

I need this function to look in a file for a certain day, then say for each flight how many people are there, in the same day.
So far I managed to get it to say how many people there are per day, but im struggling to get it to say how many people are on each flight per day.
fun interval(reserves: ArrayList<Reserves>, dayInferior: Int, daySuperior: Int) {
var count = dayInferior
var person: Int
for (reserve in reserves) {
person = 0
for (reserve in reserves) {
if (reserve.day == count && reserve.day <= daySuperior) {
person++
}
}
if (count <= daySuperior) {
println("${reserve.numFlight} Day $count has $person")
}
count++
}
}
class Reserves {
var numCc: Int?
var name: String
var numFlight: String
var day: Int
constructor(numCc: Int?, name: String, numFlight: String, day: Int) {
this.numCc = numCc
this.name = name
this.numFlight = numFlight
this.day = day
}
}
fun readFileReserves(fileNameInput: String): ArrayList<Reserves> {
val reserves: ArrayList<Reserves> = ArrayList()
val lines = File(fileNameInput).readLines()
for (line in lines) {
val parts = line.split(':')
val numCc = parts[0].toIntOrNull()
val name = parts[1]
val numFlight = parts[2]
val day = parts[3].toIntOrNull()
if (day == null || numCc == null) {
println("Invalid day")
} else {
val r = Reserves(numCc, name, numFlight, day)
reserves.add(r)
}
}
return reserves
}
I assume #Jocas means interval to get the count of Reserves between dayInferior and daySuperior.
fun interval(reserves: List<Reserves>, dayInferior: Int, daySuperior: Int) {
val map = mapReserves(reserves)
for(day in dayInferior..daySuperior) {
map.forEach {
val reservesName = it.key.first
val reservesDay = it.key.second
val reservesCount = it.value.count()
if (reservesDay == day)
print("$reservesName has $reservesCount on day passengers $day")
}
}
}
fun mapReserves(reserves: List<Reserves>): Map<Pair<String, Int>, List<Reserves>> {
val map = mutableMapOf<Pair<String, Int>, MutableList<Reserves>>()
reserves.forEach {
val key = it.numFlight to it.day
val list = map[key] ?: mutableListOf()
list.add(it)
map[key] = list
}
return map
}
// This is how you write in Kotlin. Your style is Java.
class Reserves(var numCc: Int, var name: String, var numFlight: String, var day: Int)
// Use abstraction List and MutableList instead of ArrayList
fun readFileReserves(fileNameInput: String): List<Reserves> {
val reserves = mutableListOf<Reserves>()
val lines = File(fileNameInput).readLines()
for (line in lines) {
val parts = line.split(":")
val numCc = parts[0].toIntOrNull()
val name = parts[1]
val numFlight = parts[2]
val day = parts[3].toIntOrNull()
if (day == null || numCc == null) {
println("Invalid day")
} else {
val r = Reserves(numCc, name, numFlight, day)
reserves.add(r)
}
}
return reserves
}