what's the idiomatic way to take a list and group it into tuples of size n?
eg: group into 3's with triple
val list = listOf(1,2,3,4)
val partitioned = list.groupsOf(3)
// partitioned[0] = List<Int> 1, 2, 3
// partitioned[1] = List<Int> 4
but preferably something like this
val list = listOf(1,2,3,4)
val newList = mutableListOf()
list.forGroupsOf(3) { triple: Triple<Int?> ->
newList.add( triple )
}
// partitioned[0] = Triple<Int?> 1, 2, 3
// partitioned[1] = Triple<Int?> 4, null, null
NOTE: List.groupsOf and List.forGroupsOf I made up for this example
Kotlin provides a function called chunked(n) which produces a list of lists with n elements each:
val list = listOf(1, 2, 3, 4)
val tuples = list.chunked(2).map { Tuple(it[0], it[1]) }
Or alternatively:
val list = listOf(1, 2, 3, 4)
val tuples = list.chunked(2) { Tuple(it[0], it[1]) }
Keep in mind that this produces lists with max n elements.
Related
I have multiple lists of integers.
val firstList: ArrayList<Int> = arrayListOf(1, 1, 1, 2, 3, 4)
val secondList: ArrayList<Int> = arrayListOf(1, 4, 5, 6, 6, 6, 7, 8)
val thirdList: ArrayList<Int> = arrayListOf(1, 6, 9)
...
I need to remove duplicates only among the other lists, and not within a list itself.
The result should be:
[1,1,1,2,3,4,5,6,6,6,7,8,9]
What is the best approach to do so in Kotlin?
We can filter the additional lists with a .filter and .contains, then add the result to the firstList. Not sure if this is the most efficient way, but it should work.
val firstList: ArrayList<Int> = arrayListOf(1, 1, 1, 2, 3, 4)
val secondList: ArrayList<Int> = arrayListOf(1, 4, 5, 6, 6, 6, 7, 8)
val thirdList: ArrayList<Int> = arrayListOf(1, 6, 9)
firstList += secondList.filterNot { firstList.contains(it) }
firstList += thirdList.filterNot { firstList.contains(it) }
firstList.sort() //not sure if you want the firstList to be sorted or not
You could also make it an extension function, so then it is easier to call.
fun <T> MutableCollection<T>.addOtherNoDuplicates(vararg others: Iterable<T>){
others.forEach {other ->
this += other.filterNot { this.contains(it) }
}
}
Then the call would just be:
firstList.addOtherNoDuplicates(secondList, thirdList) //add as many as you want
firstList.sort()
If you only want to use it for ArrayList, then you can replace the MutableCollection<T> with ArrayList<T> and use the sort() directly in the function itself.
If these are very long lists, you can use a MutableSet on the side to efficiently avoid adding the unwanted values.
val input = listOf(firstList, secondList, thirdList)
val allValues = mutableSetOf<Int>()
val result = mutableListOf<Int>()
for (list in input) {
val newValues = list.filterNot { it in allValues }
result.addAll(newValues)
allValues.addAll(newValues)
}
println(result)
Kotlin 1.4.72
I have a list of Ints called listOfSelectedIds
Another list will be generated called currentIds.
I want to be able to add or remove from the listOfSelectedIds based on the following condition:
If there is a ID from the currentIds that exists in the listOfSelectedIds then that ID should be removed from the listOfSelectedIds. Else if the ID does not exist then it should be added to the listOfSelectedids.
Is there any operators that do this on a list.
Example
listOfSelectedIds [1, 2, 3, 4, 5]
listOfCurrentIds [4, 5, 6, 7]
So the end result of listOfSelectedIds will be [1, 2, 3, 6, 7]
4 and 5 have been removed. And 6 and 7 has been added.
Many thanks in advance,
You can also do this in one iteration
fun main() {
val selectedIds = setOf(1, 2, 3, 4, 5) // Set A
val currentIds = setOf(4, 5, 6, 7) // Set B
println(selectedIds.xor(currentIds))
}
fun <T> Set<T>.xor(b: Set<T>): Set<T> {
val mutableB = b.toMutableSet()
return filterNot { mutableB.remove(it) } union mutableB
}
You can change your list to a Set and perform set operations. From a mathematical standpoint, it will be (A-B) U (B-A).
Subtract B from A, and A from B.
Do a union of the two sets generated from step 1.
fun main() {
val selectedIds = setOf(1, 2, 3, 4, 5) // Set A
val currentIds = setOf(4, 5, 6, 7) // Set B
val selectedIdsNotInCurrentIds = selectedIds subtract currentIds // Set A-B
val currentIdsNotInSelectedIds = currentIds subtract selectedIds // Set B-A
val result = selectedIdsNotInCurrentIds union currentIdsNotInSelectedIds // (A-B) U (B-A)
println(result)
}
Is it possible to declare a list of same values of fixed size in Kotlin. For example, if the value is 1 and the size is 5. I want to declare a list which would look like below:
[1, 1, 1, 1, 1]
I know I can declare a mutable list, and then populate it with 1's. But is there any shortcut?
Thanks in advance.
easier solution for this, (just as #deHaar answer but immutable one)
List(5) { 1 }
// -> [1, 1, 1, 1, 1]
I think you can just specify the amount of items and the value of each item like this:
fun main(args: Array<String>) {
// specify the list size
val n = 5
// specify the item value
val v = 1
// create a list of size n with v as each value
var myList = MutableList(n) {v}
// print it
println(myList)
}
The output is then
[1, 1, 1, 1, 1]
Using range operator and map function
(1..5).map { 1 })
I would like to know how can I create a List of List in the result of a reduce operation.
I've for example this lines
1,2,3,4
0,7,8,9
1,5,6,7
0,6,5,7
And I would like to get something like this
1, [[2,3,4],[5,6,7]]
0, [[7,8,9],[6,5,7]]
Thsi is my code
val parsedData = data.map { line =>
val parts = line.split(",")
val label = Integer.parseInt(parts(0))
(label, List(Integer.parseInt(parts(1)), Integer.parseInt(parts(2)), Integer.parseInt(parts(3)))
}
With this I get
1, [2,3,4]
0, [7,8,9]
1, [5,6,7]
0, [6,5,7]
But if I use a reduceByKey operation with a List.concat(_,_) I get one single List with all items concated.
parsedData.reduceByKey(List.concat(_,_))
I want a List of List, reduced by the Key.
Is there some other operation that i don't know?
Thanks a lot for your help!
Here is a working example:
val data = "1,2,3,4\n0,7,8,9\n1,5,6,7\n0,6,5,7".split("\n")
val parsedData = data.map{ line =>
val parts = line.split(",")
val label = Integer.parseInt(parts(0))
(label, List(Integer.parseInt(parts(1)), Integer.parseInt(parts(2)), Integer.parseInt(parts(3))))
}.toList
//parsedData: List[(Int, List[Int])] = List((1,List(2, 3, 4)), (0,List(7, 8, 9)), (1,List(5, 6, 7)), (0,List(6, 5, 7)))
parsedData.groupBy(_._1).mapValues(_.map(_._2))
// Map(1 -> List(List(2, 3, 4), List(5, 6, 7)), 0 -> List(List(7, 8, 9), List(6, 5, 7)))
I am not sure this is concat you are looking for.
Can you try with that:
parsedData.reduceByKey(_ :: _ :: Nil)
Which should literally create a new list with your elements inside
I have a List
val family=List("1","2","11","12","21","22","31","33","41","44","51","55")
i want to take its first n elements but the problem is that parents size is not fixed.
val familliar=List("1","2","11") //n=3
You can use take
scala> val list = List(1,2,3,4,5,6,7,8,9)
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> list.take(3)
res0: List[Int] = List(1, 2, 3)
List(1,2,3).take(100) //List(1,2,3)
The signature of take will compare the argument with index, so the incremental index will never more than argument
The signature of take
override def take(n: Int): List[A] = {
val b = new ListBuffer[A]
var i = 0
var these = this
while (!these.isEmpty && i < n) {
i += 1
b += these.head
these = these.tail
}
if (these.isEmpty) this
else b.toList
}
Use take:
val familliar = family.take(3)