已经有一个内置的方式来满足我的请求?
我知道Set是无序的
我需要做一个基于向量的集合
我需要知道泛型类型的任何值的位置,以便将它们放置在数组的相应索引中,这样我就可以避免元素的重复。
我不是在排序或定义集合的顺序。没有任何运算符违反Set约束
请注意,我知道这个实现对于任何看起来无限的类型(如整数)都不是有效的。
我需要做这件事是为了教育目的。
我已经实现了列表排序和哈希表为基础的。
现在我有这个类,它可以完美地工作:
package ads
class MySet<E : Enum<E>> {
//More details for clarify
private val maxSet = 127
private var myset = arrayOfNulls<Boolean>(maxSet)
private fun getOrdinal(eelement : E) : Int{
return eelement.ordinal
}
/*
more set operators that needs of getOrdinal
*/
fun insert(xelement: E){
myset[getOrdinal(xelement)] = true
}
}
import ads.MySet as RawSet
enum class MyColors{
Red,
Green,
Blue,
Yellow,
Black,
Mint;
}
fun main() {
val myfavc = RawSet<MyColors>()
val yourfavc = RawSet<MyColors>()
//Following operations...
myfavc.insert(MyColors.Red)
yourfavc.insert(MyColors.Blue)
}
我现在需要以同样的方式创建另一个类,但是使用已经在kotlin中定义的抽象类型。
package ads
class MySet<T> {
//More details for clarify
private val maxSet = 127
private var myset = arrayOfNulls<Boolean>(maxSet)
private fun getOrdinal(telement : T) : Int{
/*
For any abstract type return the order of any element
checks if the integer is not greater than maxSet otherwhise it
throws an Exception or manages this istance in other way
*/
}
/*
more set operators that needs of getOrdinal
*/
fun insert(xelement: T){
myset[getOrdinal(xelement)] = true
}
}
import ads.MySet as RawSeT
//Istance using Int
fun main() {
val myfav = RawSet<Int>()
val yourfav = RawSet<Int>()
//Following operations...
myfav.insert(11)
yourfav.insert(123)
}
我猜没有内置的方法可以在通用的方式中做到这一点。但是我还在学习kotlin,所以也许我错过了一些有用的东西。
我不是要求做我的论文。
我不需要一个完整的替代解决方案,我应该自己找到,但是我愿意阅读任何可以帮助我澄清抽象类型如何在Kotlin(或编程语言)中工作的提示或资源,如:
如何排序
如果任何类型的任何值都可以根据其位置进行比较(像c>
值范围/最大值表示任何"明显"infinite">
谢谢你!
注:请考虑到我不是一个英语母语的人,耐心点!
Enum
按声明顺序隐式排序,且每个枚举的实例数量是有限的,因此它们可以全局排序,其序数可以表示为Int
。
Int
s(以及Byte
s和Char
s)是自然有序的,并且具有范围(Int.MIN_VALUE..Int.MAX_VALUE
等),因此它们每个都可以有一个序数表示为Int
。
所有实现Comparable
接口的类型都可以成对比较,并且它们的实例的任何子集都可以有序,但这并不意味着它们中的每一个在所有可能的实例中都有一些全局的Int
序数,因为Int
的集合是有限的(2^32项),而所有泛型T
的唯一实例的集合可以是可数的无限的(如BigInteger
)甚至不可数的(如Double
)(参见维基关于基数)。
所有其他类型甚至不能成对比较(没有尊重Comparator<T>
)。
因此,您需要手动限制即将添加到您的集合中的每个T
的实例,并且要么手动排序它们,要么提供尊重的Comparator<T>
来构建您需要用于后续序数评估的Map<T, Int>
:
class SetOfSomehowOrderedInstancesOfType<T>(private val order: Map<T, Int>) {
private val maxSet = order.size
private var myset = BooleanArray(order.size)
private fun getOrdinal(eelement: T): Int {
return order[eelement] ?: throw RuntimeException("Order unknown")
}
fun insert(xelement: T) {
myset[getOrdinal(xelement)] = true
}
}
用法:
fun main() {
val myFavouriteRealNumbersInMyFavouriteOrder =
listOf(99.2123, -2355.12, 1.1, 3.14, 100.0, 123214214215.123331322145)
val myfavc = SetOfSomehowOrderedInstancesOfType<Double>(myFavouriteRealNumbersInMyFavouriteOrder.mapToIndex())
myfavc.insert(99.2123) //will be inserted with ordinal = 0
val myFavouriteRealNumbersInNaturalOrder = myFavouriteRealNumbersInMyFavouriteOrder.sorted()
val yourfavc = SetOfSomehowOrderedInstancesOfType<Double>(myFavouriteRealNumbersInNaturalOrder.mapToIndex())
yourfavc.insert(99.2123) //will be inserted with ordinal = 3
}
或者您可以定义Orderable
和Ordinator<T>
接口(类似于Comparable<T>
和Comparator<T>
)并使用它们确定序数:
fun interface Ordinator<T> {
fun getOrderOf(x : T) : Int
}
interface Orderable {
val order : Int
}
class MySet<T>(private val ordinator: Ordinator<T>? = null) {
private val maxSet = 127
private var myset = BooleanArray(maxSet)
private fun getOrdinal(eelement: T) = when {
eelement is Orderable -> eelement.order
ordinator != null -> ordinator.getOrderOf(eelement)
else -> throw RuntimeException()
}
fun insert(xelement: T) {
myset[getOrdinal(xelement)] = true
}
}
也可以定义辅助函数,概括前面的方法:
fun <T> ordinatorOf(order: List<T>) = object : Ordinator<T> {
private val order = order.mapToIndex()
override fun getOrderOf(x: T) = this.order[x] ?: throw RuntimeException()
}
用法:
val stringsOrderedByTheirLength = MySet<String> { it.length }
stringsOrderedByTheirLength.insert("aaa") //will be inserted with ordinal = 3
val myFavouriteRealNumbersInMyFavouriteOrder =
listOf(99.2123, -2355.12, 1.1, 3.14, 100.0, 123214214215.123331322145)
val myfavc = MySet(ordinatorOf(myFavouriteRealNumbersInMyFavouriteOrder))
myfavc.insert(99.2123) //will be inserted with ordinal = 0
正如有人向我指出的那样,一些抽象类型表示一个实例实数是不容易做到的。
枚举类的实现完美无缺,但我的大学教授拒绝了,因为我需要为相同数据结构的每个实现使用相同的语法。
其他的实现我有
- HashTableSet<T>
- OrderedListSet<T>
他们只要求一个抽象类型,可以是任何类型,他们将没有问题。
我需要对ArraySet<E : Enum<E>>
所以如果用泛型不能很容易地做到这一点,直接…
我在考虑把它们混在一起。
就像我的T类型一样它会创建一个名为"domain"的对象;因此,无论插入什么元素,在将它们放入set的数组之前,它都将它们按照特定的顺序放入其中,以模拟enum的操作。
我猜枚举不能在运行时动态地定义。
然后可能我必须定义Domain<T>
作为一个私有类/对象(不确定):
- 收集ArraySet(在MySet之上)的insert的操作符。insert()
- 将元素与已经在 中的元素进行比较。
- 一旦被命令删除所有的组
- 重新安排整个布尔数组每次插入是基于如何使用域增长。(或者找到一个不同的算法,部分重新排列布尔数组)
你觉得怎么样?
多多指教,谢谢。