Skip to content

Commit

Permalink
v1.4.4 (#72)
Browse files Browse the repository at this point in the history
  • Loading branch information
lbressler13 authored Apr 21, 2024
1 parent e2c9e69 commit e0bb89b
Show file tree
Hide file tree
Showing 29 changed files with 901 additions and 636 deletions.
2 changes: 1 addition & 1 deletion kotlin-utils/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {
}

group = "xyz.lbres"
version = "1.3.4"
version = "1.4.4"

repositories {
mavenCentral()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package xyz.lbres.kotlinutils.set.multiset

import xyz.lbres.kotlinutils.set.multiset.utils.CountsMap
import xyz.lbres.kotlinutils.set.multiset.utils.performIntersect
import xyz.lbres.kotlinutils.set.multiset.utils.performMinus
import xyz.lbres.kotlinutils.set.multiset.utils.performPlus

/**
* Interface for set that allows multiple occurrences of a value.
* The interface supports only read access to the values.
Expand Down Expand Up @@ -55,7 +60,9 @@ interface MultiSet<E> : Collection<E> {
* @param multiSet2 [MultiSet]<E>: second MultiSet in addition
* @return [MultiSet]<E>: MultiSet containing all values from both sets
*/
fun <E> genericPlus(multiSet1: MultiSet<E>, multiSet2: MultiSet<E>): MultiSet<E> = genericMultiSetPlus(multiSet1, multiSet2)
fun <E> genericPlus(multiSet1: MultiSet<E>, multiSet2: MultiSet<E>): MultiSet<E> {
return performPlus(CountsMap.from(multiSet1), multiSet2)
}

/**
* [minus] implementation that can be used with any [MultiSet] implementations.
Expand All @@ -65,7 +72,9 @@ interface MultiSet<E> : Collection<E> {
* @param multiSet2 [MultiSet]<E>: second MultiSet in subtraction
* @return [MultiSet]<E>: MultiSet containing the items in the first MultiSet but not the second
*/
fun <E> genericMinus(multiSet1: MultiSet<E>, multiSet2: MultiSet<E>): MultiSet<E> = genericMultiSetMinus(multiSet1, multiSet2)
fun <E> genericMinus(multiSet1: MultiSet<E>, multiSet2: MultiSet<E>): MultiSet<E> {
return performMinus(CountsMap.from(multiSet1), multiSet2)
}

/**
* [minus] implementation that can be used with any [MultiSet] implementations.
Expand All @@ -75,6 +84,8 @@ interface MultiSet<E> : Collection<E> {
* @param multiSet2 [MultiSet]<E>: second MultiSet in intersect
* @return [MultiSet]<E>: MultiSet containing only values that are in both sets
*/
fun <E> genericIntersect(multiSet1: MultiSet<E>, multiSet2: MultiSet<E>): MultiSet<E> = genericMultiSetIntersect(multiSet1, multiSet2)
fun <E> genericIntersect(multiSet1: MultiSet<E>, multiSet2: MultiSet<E>): MultiSet<E> {
return performIntersect(CountsMap.from(multiSet1), multiSet2)
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package xyz.lbres.kotlinutils.set.multiset

// TODO count consistent
import xyz.lbres.kotlinutils.general.simpleIf

/**
* Create a new MultiSet with the results of applying the transform function to each value in the current MultiSet.
Expand Down Expand Up @@ -63,7 +63,7 @@ inline fun <E> MultiSet<E>.filterNotToSet(predicate: (E) -> Boolean): MultiSet<E
/**
* Create a list with the results of applying the transform function to each value in the current MultiSet.
* Requires a [transform] function that returns the same value for every occurrence of an element.
* To use a function that does not return the same value for every occurrence, see [map].
* To use a function that does not return the same value for every occurrence, see [Collection.map].
*
* @param transform (E) -> T: transformation function, which returns the same value for every occurrence of an element
* @return [List]<T>: list with transformed values
Expand All @@ -80,7 +80,7 @@ inline fun <E, T> MultiSet<E>.mapConsistent(transform: (E) -> T): List<T> {
/**
* Create a list containing only elements that match the given predicate.
* Requires a [predicate] function that returns the same value for every occurrence of an element.
* To use a function that does not return the same value for every occurrence, see [filter].
* To use a function that does not return the same value for every occurrence, see [Collection.filter].
*
* @param predicate (E) -> [Boolean]: predicate to use for filtering, which returns the same value for every occurrence of an element
* @return [List]<E>: list containing only values for which [predicate] returns `true`
Expand All @@ -101,7 +101,7 @@ inline fun <E> MultiSet<E>.filterConsistent(predicate: (E) -> Boolean): List<E>
/**
* Create a list containing only elements that do not match the given predicate.
* Requires a [predicate] function that returns the same value for every occurrence of an element.
* To use a function that does not return the same value for every occurrence, see [filterNot].
* To use a function that does not return the same value for every occurrence, see [Collection.filterNot].
*
* @param predicate (E) -> [Boolean]: predicate to use for filtering, which returns the same value for every occurrence of an element
* @return [List]<E>: list containing only values for which [predicate] returns `false`
Expand Down Expand Up @@ -255,3 +255,17 @@ inline fun <E, R : Comparable<R>> MultiSet<E>.maxByOrNullConsistent(selector: (E

return distinctValues.maxByOrNull(selector)
}

/**
* Count number of values matching predicate
* Requires a [predicate] function that returns the same value for every occurrence of an element.
* To use a function that does not return the same value for every occurrence, see [Collection.count].
*
* @param predicate (E) -> [Boolean]: predicate to use for counting, which returns the same value for every occurrence of an element
* @return [Int]: number of values for which [predicate] return `true`
*/
inline fun <E> MultiSet<E>.countConsistent(predicate: (E) -> Boolean): Int {
return distinctValues.fold(0) { acc: Int, element: E ->
simpleIf(predicate(element), { acc + getCountOf(element) }, { acc })
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,76 @@
package xyz.lbres.kotlinutils.set.multiset.const

import xyz.lbres.kotlinutils.general.tryOrDefault
import xyz.lbres.kotlinutils.internal.constants.Suppressions
import xyz.lbres.kotlinutils.set.multiset.MultiSet
import xyz.lbres.kotlinutils.set.multiset.utils.CountsMap
import xyz.lbres.kotlinutils.set.multiset.utils.performIntersect
import xyz.lbres.kotlinutils.set.multiset.utils.performMinus
import xyz.lbres.kotlinutils.set.multiset.utils.performPlus

/**
* [MultiSet] implementation where values of elements are assumed to be constant.
* Behavior is not defined if values of elements are changed (i.e. elements are added to a mutable list).
*/
sealed class ConstMultiSet<E> : MultiSet<E>
sealed class ConstMultiSet<E> : MultiSet<E> {
// required because ConstMultiSet is a public class. Must be CountsMap<E>
protected abstract val counts: Any
private val _counts: CountsMap<E>
@Suppress(Suppressions.UNCHECKED_CAST)
get() = counts as CountsMap<E>

override fun plus(other: MultiSet<E>): MultiSet<E> = performPlus(_counts, other)
override fun minus(other: MultiSet<E>): MultiSet<E> = performMinus(_counts, other)
override fun intersect(other: MultiSet<E>): MultiSet<E> = performIntersect(_counts, other)

@Suppress(Suppressions.FUNCTION_NAME)
infix fun `+c`(other: ConstMultiSet<E>): ConstMultiSet<E> = plusC(other)
@Suppress(Suppressions.FUNCTION_NAME)
infix fun `-c`(other: ConstMultiSet<E>): ConstMultiSet<E> = minusC(other)

/**
* Alternate version of [plus], which returns a ConstMultiSet
*
* @param other [ConstMultiSet]<E>: values to add to this MultiSet
* @return [ConstMultiSet]<E>: ConstMultiSet containing all values from both MultiSets
*/
fun plusC(other: ConstMultiSet<E>): ConstMultiSet<E> = performPlus(_counts, other, true) as ConstMultiSet<E>

/**
* Alternate version of [minus], which returns a ConstMultiSet
*
* @param other [ConstMultiSet]<E>: values to subtract from this MultiSet
* @return [ConstMultiSet]<E>: ConstMultiSet containing the items in this MultiSet but not the other
*/
fun minusC(other: ConstMultiSet<E>): ConstMultiSet<E> = performMinus(_counts, other, true) as ConstMultiSet<E>

/**
* Alternate version of [intersect], which returns a ConstMultiSet
*
* @param other [ConstMultiSet]<E>: values to intersect with this MultiSet
* @return [ConstMultiSet]<E>: ConstMultiSet containing only values that are in both MultiSets
*/
infix fun intersectC(other: ConstMultiSet<E>): ConstMultiSet<E> = performIntersect(_counts, other, true) as ConstMultiSet<E>

override fun getCountOf(element: E): Int = _counts.getCountOf(element)
override fun contains(element: E): Boolean = _counts.contains(element)
override fun containsAll(elements: Collection<E>): Boolean = _counts.containsAll(elements)
override fun isEmpty(): Boolean = _counts.isEmpty()

override fun hashCode(): Int {
val hashCode = _counts.hashCode()
return 31 * hashCode + MultiSet::class.java.name.hashCode()
}

override fun equals(other: Any?): Boolean {
return if (other is ConstMultiSet<*>) {
_counts == other._counts
} else {
tryOrDefault(false, listOf(ClassCastException::class)) {
@Suppress(Suppressions.UNCHECKED_CAST)
other as MultiSet<E>
_counts == CountsMap.from(other)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package xyz.lbres.kotlinutils.set.multiset.const

import xyz.lbres.kotlinutils.generic.ext.ifNull
import xyz.lbres.kotlinutils.set.multiset.MultiSet
import xyz.lbres.kotlinutils.set.multiset.utils.CountsMap

// final implementation of ConstMultiSet
internal class ConstMultiSetImpl<E>(private val elements: Collection<E>, initialCounts: CountsMap<E>? = null) : ConstMultiSet<E>(), AbstractConstMultiSetImpl<E> {
internal class ConstMultiSetImpl<E>(private val elements: Collection<E>, initialCounts: CountsMap<E>? = null) : ConstMultiSet<E>() {
override val size: Int = elements.size
override val distinctValues: Set<E>
private val string: String
Expand All @@ -14,20 +13,10 @@ internal class ConstMultiSetImpl<E>(private val elements: Collection<E>, initial
init {
counts = initialCounts.ifNull { CountsMap.from(elements) }
distinctValues = counts.distinct
string = counts.toString()
string = "[${elements.joinToString()}]"
}

override fun getCountOf(element: E): Int = counts.getCountOf(element)
override fun contains(element: E): Boolean = counts.contains(element)
override fun containsAll(elements: Collection<E>): Boolean = counts.containsAll(elements)

override fun plus(other: MultiSet<E>): MultiSet<E> = super<AbstractConstMultiSetImpl>.plus(other)
override fun minus(other: MultiSet<E>): MultiSet<E> = super<AbstractConstMultiSetImpl>.minus(other)
override fun intersect(other: MultiSet<E>): MultiSet<E> = super<AbstractConstMultiSetImpl>.intersect(other)

override fun isEmpty(): Boolean = counts.isEmpty()
fun toCountsMap(): CountsMap<E> = counts
override fun iterator(): Iterator<E> = elements.iterator()
override fun hashCode(): Int = getHashCode()
override fun equals(other: Any?): Boolean = other is MultiSet<*> && equalsSet(other)
override fun toString(): String = string
}
Loading

0 comments on commit e0bb89b

Please sign in to comment.