com.jtransc.ds.collectionutils.kt Maven / Gradle / Ivy
/*
* Copyright 2016 Carlos Ballesteros Velasco
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jtransc.ds
import java.util.*
inline fun Iterable.cast() = this.filterIsInstance()
fun queueOf(vararg items: T): java.util.Queue = LinkedList(items.toList())
fun List>.uniqueMap(): HashMap? {
val h = hashMapOf()
val okay = this.all { x ->
val y = h.put(x.first, x.second)
(y == null) || (y == x.second)
}
return if (okay) h else null
}
val List.head: T get() = this.first()
val List.tail: List get() = this.drop(1)
fun Map.flip(): Map = this.map { it.value to it.key }.toMap()
val Pair, List>.zipped: List> get() {
return this.first.zip(this.second)
}
class Queue() : Iterable {
constructor(items: Iterable) : this() {
queueAll(items)
}
private val data = LinkedList()
val hasMore: Boolean get() = data.isNotEmpty()
val length: Int get() = data.size
fun queue(value: T): T {
data.addFirst(value)
return value
}
fun queueAll(items: Iterable): Queue {
for (item in items) queue(item)
return this
}
fun dequeue(): T {
return data.removeLast()
}
override fun iterator(): Iterator = data.iterator()
}
class Stack(
private var data: ArrayList = arrayListOf()
): Iterable {
val hasMore: Boolean get() = data.isNotEmpty()
val length: Int get() = data.size
fun push(value: T): T {
data.add(value)
return value
}
fun pop(): T {
return data.removeAt(data.size - 1)
}
fun clone(): Stack = Stack(ArrayList(data))
override fun toString(): String = toList().toString()
fun toList(): List = data.toList()
override fun iterator(): Iterator = data.iterator()
fun isEmpty() = !hasMore
fun isNotEmpty() = hasMore
}
// @TODO: Make clearer!
fun List.flatMapInChunks(chunkSize: Int, handler: (items: List) -> List): List {
var out = this
var n = 0
while (n + chunkSize <= out.size) {
//println("IN: $out")
val extracted = out.slice(n until n + chunkSize)
val toInsert = handler(extracted)
out = out.slice(0 until n) + toInsert + out.slice(n + chunkSize until out.size)
//println("OUT: $out")
n++
}
return out
}
fun List.flatMapInChunks2(chunkSize: Int, handler: (items: List) -> List): List {
val out = arrayListOf()
for (n in 0 until this.size / chunkSize) {
//println("IN: $out")
out.addAll(handler(this.slice(n * chunkSize until n * chunkSize + chunkSize)))
}
return out
}
fun List?.createPairs(): List> {
return this?.flatMapInChunks2(2) { listOf(Pair(it[0], it[1])) } ?: listOf()
}
fun Map.toHashMap(): HashMap {
val out = hashMapOf()
for (pair in this) {
out.put(pair.key, pair.value)
}
return out
}
fun Iterable.stripNulls(): List {
return this.filter { it != null }.map { it!! }
}
fun List.toTypedArray2(clazz: Class<*>): Any {
val items = this
val typedArray = java.lang.reflect.Array.newInstance(clazz, items.size)
for (n in 0 until items.size) {
java.lang.reflect.Array.set(typedArray, n, items[n])
}
return typedArray
}
fun List?.toTypedArray2(): Any? {
if (this != null && this.isEmpty()) {
//println("empty array!")
}
return this?.toTypedArray2(this.getOrNull(0)?.javaClass ?: Any::class.java)
}
data class DiffResult(val both: List, val justFirst: List, val justSecond: List)
fun Iterable.diff(that: Iterable): DiffResult {
val first = this
val second = that
val firstSet = first.toSet()
val secondSet = second.toSet()
return DiffResult(
both = first.filter { it in secondSet },
justFirst = first.filter { it !in secondSet },
justSecond = second.filter { it !in firstSet }
)
}
infix fun Int.clearFlags(that:Int) = (this and that.inv())
infix fun Int.hasFlag(that:Int) = (this and that) != 0
infix fun Int.hasAnyFlags(that:Int) = (this and that) != 0
infix fun Int.hasAllFlags(that:Int) = (this and that) == that
fun List?>?.concatNotNull(): List {
val out = arrayListOf()
if (this != null) for (l in this) {
if (l != null) {
for (i in l) {
if (i != null) out += i
}
}
}
return out
}
fun Concat(vararg list: List?): List {
var out = listOf()
for (l in list) if (l != null) out += l
return out
}
fun List.split(separator: T): List> {
val out = arrayListOf>()
val part = arrayListOf()
fun flush() {
out += part.toList()
part.clear()
}
for (item in this) {
if (item == separator) {
flush()
} else {
part += item
}
}
flush()
return out
}